home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Sprite 1984 - 1993
/
Sprite 1984 - 1993.iso
/
src
/
cmds
/
fsinstall
/
RCS
/
fsmake.c,v
< prev
Wrap
Text File
|
1992-04-14
|
106KB
|
4,045 lines
head 1.14;
branch ;
access ;
symbols ;
locks jhh:1.14; strict;
comment @ * @;
1.14
date 90.02.17.23.47.50; author nelson; state Exp;
branches ;
next 1.13;
1.13
date 89.12.15.15.16.40; author ouster; state Exp;
branches ;
next 1.12;
1.12
date 89.12.13.14.06.45; author rab; state Exp;
branches ;
next 1.11;
1.11
date 89.11.29.16.49.52; author ouster; state Exp;
branches ;
next 1.10;
1.10
date 89.11.27.21.58.00; author rab; state Exp;
branches ;
next 1.9;
1.9
date 89.11.27.21.44.16; author jhh; state Exp;
branches ;
next 1.8;
1.8
date 89.11.27.14.31.45; author rab; state Exp;
branches ;
next 1.7;
1.7
date 89.11.11.22.55.11; author rab; state Exp;
branches ;
next 1.6;
1.6
date 89.06.19.13.18.14; author mnelson; state Exp;
branches ;
next 1.5;
1.5
date 89.05.19.17.40.11; author mnelson; state Exp;
branches ;
next 1.4;
1.4
date 89.05.19.16.56.39; author mnelson; state Exp;
branches ;
next 1.3;
1.3
date 89.05.15.19.39.56; author mnelson; state Exp;
branches ;
next 1.2;
1.2
date 89.05.03.19.00.24; author mnelson; state Exp;
branches ;
next 1.1;
1.1
date 89.05.02.10.50.04; author mnelson; state Exp;
branches ;
next ;
desc
@@
1.14
log
@Added ``newLabel'' option.
@
text
@/*
* fsmake.c --
*
* Make a sprite file system on a raw disk.
*
* IMPORTANT NOTE ABOUT PORTABILITY:
*
* I use the sprite directory format even when I am reading a UNIX
* directory. I can get a way with this because they are the same. The
* reason why I don't use the UNIX one is that on a PMAX there are some
* defines in "/usr/include/sys/dir.h" which screw up the compilation
* of this file. If this runs on a UNIX system that does not have
* a compatible directory format then the code in CopyTree must be
* modified.
*
* Copyright (C) 1989 by Digital Equipment Corporation, Maynard MA
*
* All Rights Reserved
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose and without fee is hereby granted,
* provided that the above copyright notice appear in all copies and that
* both that copyright notice and this permission notice appear in
* supporting documentation, and that the name of Digital not be
* used in advertising or publicity pertaining to distribution of the
* software without specific, written prior permission.
*
* Digitial disclaims all warranties with regard to this software, including
* all implied warranties of merchantability and fitness. In no event shall
* Digital be liable for any special, indirect or consequential damages or
* any damages whatsoever resulting from loss of use, data or profits,
* whether in an action of contract, negligence or other tortious action,
* arising out of or in connection with the use or performance of this
* software.
*/
#ifndef lint
static char rcsid[] = "$Header: /sprite/src/admin/fsinstall/RCS/fsmake.c,v 1.13 89/12/15 15:16:40 ouster Exp $ SPRITE (Berkeley)";
#endif
#include "sprite.h"
#include "option.h"
#include "diskUtils.h"
#include <stdio.h>
#include <sys/file.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/dir.h>
#include <assert.h>
#include <sys/time.h>
#ifdef direct
#undef direct
#endif
#if defined(sprite) || defined(sun)
#define S_GFDIR S_IFDIR
#define S_GFMT S_IFMT
#define S_GFLNK S_IFLNK
#define S_GFREG S_IFREG
#endif
/*
* Constants settable via the command line.
*/
int kbytesToFileDesc = 4; /* The ratio of kbytes to
* the number of file descriptors */
Boolean printOnly = FALSE; /* Stop after computing the domain header
* and just print it out. No disk writes */
Boolean overlapBlocks = FALSE; /* Allow filesystem blocks to overlap track
* boundaries. Some disk systems can't deal. */
char *deviceName; /* Set to "rsd0" or "rxy1", etc. */
char *partName; /* Set to "a", "b", "c" ... "g" */
char defaultFirstPartName[] = "a";
char *diskType = NULL; /* Type of disk (e.g. rz23) */
int spriteID = 1; /* This machines sprite id. */
char *devFileName = NULL; /* Name of file that contains devices to
* create. */
char *dirName = NULL; /* Name of directory that contains files to
* copy to the disk. */
Boolean newLabel = FALSE;
Option optionArray[] = {
{OPT_STRING, "dev", (Address)&deviceName,
"Required: Name of device, eg \"rsd0\" or \"rxy1\""},
{OPT_STRING, "part", (Address)&partName,
"Required: Partition ID: (a, b, c, d, e, f, g)"},
{OPT_TRUE, "overlap", (Address)&overlapBlocks,
"Overlap filesystem blocks across track boundaries (FALSE)"},
{OPT_INT, "ratio", (Address)&kbytesToFileDesc,
"Ratio of Kbytes to file descriptors (4)"},
{OPT_TRUE, "test", (Address)&printOnly,
"Test: print results, don't write disk (FALSE)"},
{OPT_FALSE, "write", (Address)&printOnly,
"Write the disk (TRUE)"},
{OPT_STRING, "type", (Address)&diskType,
"Type of disk. Used to look up disk info in /etc/disktab"},
{OPT_INT, "sid", (Address)&spriteID,
"Sprite ID of this workstation"},
{OPT_STRING, "dir", (Address)&dirName,
"Directory to copy files from"},
{OPT_STRING, "devFile", (Address)&devFileName,
"File that contains devices to create"},
{OPT_TRUE, "newLabel", (Address)&newLabel,
"Overwrite the current label on the disk if there is one"},
};
int numOptions = sizeof(optionArray) / sizeof(Option);
/*
* Structure used to peruse Sprite directories.
*/
typedef struct DirIndexInfo {
Fsdm_FileDescriptor *fdPtr; /* The file descriptor being
* read. */
int blockNum; /* Block that is being read,
* written, or allocated. */
int blockAddr; /* Address of directory block
* to read. */
int dirOffset; /* Offset of the directory entry
* that we are currently examining
* in the directory. */
char dirBlock[FS_BLOCK_SIZE]; /* Where directory data is
* stored. */
} DirIndexInfo;
/*
* Time of day when this program runs.
*/
struct timeval curTime;
/*
* Forward Declarations.
*/
void SetSummaryInfo();
void SetDomainHeader();
void SetDiskGeometry();
void SetDomainParts();
void WriteAllFileDescs();
void WriteAndInitDataBitmap();
unsigned char *ReadFileDescBitmap();
void WriteFileDescBitmap();
unsigned char *ReadBitmap();
void WriteBitmap();
char *MakeFileDescBitmap();
Disk_Info *ScanDiskTab();
static Fslcl_DirEntry *OpenDir();
Fslcl_DirEntry *NextDirEntry();
static void CloseDir();
Fslcl_DirEntry *AddToDirectory();
void CreateDir();
void MarkDataBitmap();
void InitDesc();
void CopyTree();
void ReadFileDesc();
void WriteFileDesc();
void MakeDevices();
void WriteRootDirectory();
/*
* Macro to get a pointer into the bit map for a particular block.
*/
#define BlockToCylinder(domainPtr, blockNum) \
(blockNum) / (domainPtr)->geometry.blocksPerCylinder
#define GetBitmapPtr(domainPtr, bitmapPtr, blockNum) \
&((bitmapPtr)[BlockToCylinder(domainPtr, blockNum) * \
bytesPerCylinder + (blockNum) % (domainPtr)->geometry.blocksPerCylinder / 2])
/*
* Macros to convert physical block numbers to virtual block numbers. All direct
* blocks are virtual, indirect blocks are physical.
*/
#define VirtToPhys(blockNum) \
((blockNum) + (domainPtr)->dataOffset * FS_FRAGMENTS_PER_BLOCK)
#define PhysToVirt(domainPtr,blockNum) \
((blockNum) - (domainPtr)->dataOffset * FS_FRAGMENTS_PER_BLOCK)
/*
* Macro to mark the file descriptor bit map.
*/
#define MarkFDBitmap(num,bitmapPtr) \
(bitmapPtr)[(num) >> 3] |= (1 << (7 -((num) & 7)))
int freeFDNum; /* The currently free file descriptor.*/
int freeBlockNum; /* The currently free data block. */
Fsdm_FileDescriptor devFD; /* The file descriptor for the dev
* directory. */
Fsdm_FileDescriptor *devFDPtr; /* Pointer to the file descriptor for
* the dev directory. */
int devFDNum; /* The file number of the dev
* directory. */
int partFID; /* The file id of the partition that
* we are initializing. */
Fsdm_DomainHeader *domainPtr; /* The domain the we are initializing.*/
int partition; /* The partition that we are
* initializing. */
Disk_Info *diskInfoPtr; /* Information about the disk that
* we are initializing. */
Fsdm_SummaryInfo *summaryPtr; /* Summary information for the domain.*/
unsigned char *fdBitmapPtr; /* Pointer to the file descriptor
* bitmap. */
unsigned char *cylBitmapPtr; /* Pointer to the cylinder bit map. */
int bytesPerCylinder;/* The number of bytes in
* the bitmap for a cylinder.*/
/*
* Some number of sectors in the root partition must be allocated to the
* boot program. The default is for the new filesystem to have the same
* number of boot sectors as the old filesystem. If the disk did not
* previously have a filesystem, or if the domain header cannot be found,
* then the following number of boot sectors are allocated. The standard
* Sun format is for the summary sector to be in sector #17. 16 boot sectors
* and one disk label fill the first 17 sectors.
*/
int defaultBootSectors = 16;
int bootSectors = -1;
/*
*----------------------------------------------------------------------
*
* main --
*
* Create the required file names from the command line
* arguments. Then open the first partition on the disk
* because it contains the disk label, and open the partition
* that is to be formatted.
*
* Results:
* None.
*
* Side effects:
* Calls MakeFilesystem
*
*----------------------------------------------------------------------
*/
main(argc, argv)
int argc;
char *argv[];
{
char answer[10];
char partitionName[64];
int status;
static char block[DEV_BYTES_PER_SECTOR];
int i;
gettimeofday(&curTime, NULL);
(void)Opt_Parse(argc, argv, optionArray, numOptions, 0);
if (deviceName == (char *)0) {
fprintf(stderr,"Specify device name with -dev option\n");
exit(1);
}
if (partName == (char *)0) {
fprintf(stderr,"Specify partition with -part option\n");
exit(1);
}
if (spriteID == 0) {
fprintf(stderr, "Specify sprite id with -sid option\n");
exit(1);
}
bootSectors = defaultBootSectors;
if (!printOnly) {
printf("The \"-write\" option will cause fsmake to overwrite the current filesystem.\nDo you really want to do this?[y/n] ");
if (scanf("%10s",answer) != 1) {
exit(0);
}
if ((*answer != 'y') && (*answer != 'Y')) {
exit(0);
}
}
if (partName[0] != 'a' && partName[0] != 'c') {
fprintf(stderr, "Can only format partitions a or c\n");
exit(1);
}
/*
* Gen up the name of the first partition on the disk.
*/
sprintf(partitionName, "/dev/%s%s", deviceName, partName);
if (printOnly) {
partFID = open(partitionName, O_RDONLY);
} else {
partFID = open(partitionName, O_RDWR);
}
if (partFID < 0 ) {
perror("Can't open first partition");
exit(1);
}
printf("fsmake based on 4K filesystem blocks\n");
partition = partName[0] - 'a';
diskInfoPtr = NULL;
if (!newLabel) {
/*
* See if we can read the copy of the super block at the beginning
* of the partition to find out basic disk geometry and where to
* write the domain header. This will only work with disks that
* have either a sun label or a sprite label.
*/
diskInfoPtr = Disk_ReadDiskInfo(partFID, partition);
}
if (diskInfoPtr == NULL && diskType != NULL) {
/*
* See if we can find the information in /etc/disktab.
*/
diskInfoPtr = ScanDiskTab();
}
if (diskInfoPtr == NULL) {
fprintf(stderr,"MakeFilesystem: Unable to read super block.\n");
return(1);
}
/*
* Clear out the old summary sector and domain header. This is especially
* important if we are going to move them.
*/
if ((!printOnly) && (diskInfoPtr->summarySector != -1)) {
status = Disk_SectorWrite(partFID, diskInfoPtr->summarySector,1, block);
if (status != SUCCESS) {
perror("Clear of old summary sector failed");
return(status);
}
for (i = 0; i < diskInfoPtr->numDomainSectors; i++) {
status = Disk_SectorWrite(partFID, diskInfoPtr->domainSector+i,
1, block);
if (status != SUCCESS) {
perror("Clear of old domain header failed");
return(status);
}
}
}
/*
* The disk did not previously have a filesystem on it.
*/
if (diskInfoPtr->summarySector == -1) {
diskInfoPtr->summarySector = bootSectors + 1;
diskInfoPtr->domainSector = bootSectors + 2;
}
domainPtr = (Fsdm_DomainHeader *)
malloc((unsigned) diskInfoPtr->numDomainSectors * DEV_BYTES_PER_SECTOR);
SetDomainHeader();
bytesPerCylinder = (domainPtr->geometry.blocksPerCylinder + 1) / 2;
Disk_PrintDomainHeader(domainPtr);
if (!printOnly) {
assert(diskInfoPtr->domainSector >= 0);
status = Disk_SectorWrite(partFID, diskInfoPtr->domainSector,
diskInfoPtr->numDomainSectors, (Address)domainPtr);
if (status != 0) {
perror("DomainHeader write failed");
return(status);
}
}
summaryPtr = (Fsdm_SummaryInfo *) malloc(DEV_BYTES_PER_SECTOR);
SetSummaryInfo();
Disk_PrintSummaryInfo(summaryPtr);
if (!printOnly) {
assert(diskInfoPtr->summarySector >= 0);
status = Disk_SectorWrite(partFID, diskInfoPtr->summarySector, 1,
(Address)summaryPtr);
if (status != 0) {
perror("Summary sector write failed");
return(status);
}
}
WriteAllFileDescs();
WriteAndInitDataBitmap();
WriteRootDirectory();
/*
* We now have a good empty file system. Add any files and devices
* that need to be added.
*/
if (dirName != NULL) {
Fsdm_FileDescriptor rootDesc;
fdBitmapPtr = ReadFileDescBitmap();
freeFDNum = 3;
cylBitmapPtr = ReadBitmap();
freeBlockNum = 1;
ReadFileDesc(FSDM_ROOT_FILE_NUMBER, &rootDesc);
CopyTree(dirName, FSDM_ROOT_FILE_NUMBER, &rootDesc,
FSDM_ROOT_FILE_NUMBER, FALSE, "/");
WriteFileDesc(FSDM_ROOT_FILE_NUMBER, &rootDesc);
if (devFileName != NULL) {
if (devFDPtr == NULL) {
fprintf(stderr, "Couldn't find /dev\n");
exit(1);
}
MakeDevices();
}
if (!printOnly) {
assert(diskInfoPtr->summarySector);
status = Disk_SectorWrite(partFID, diskInfoPtr->summarySector, 1,
(Address)summaryPtr);
if (status != 0) {
perror("Summary sector write failed (2)");
exit(status);
}
WriteFileDescBitmap(fdBitmapPtr);
WriteBitmap(cylBitmapPtr);
}
}
fflush(stderr);
fflush(stdout);
(void)close(partFID);
exit(0);
}
/*
*----------------------------------------------------------------------
*
* SetDomainHeader --
*
* Compute the domain header based on the partition size and
* other basic disk parameters.
*
* Results:
* A return code.
*
* Side effects:
* Fill in the domain header.
*
*----------------------------------------------------------------------
*/
void
SetDomainHeader()
{
register Fsdm_Geometry *geoPtr;
domainPtr->magic = FSDM_DOMAIN_MAGIC;
domainPtr->firstCylinder = diskInfoPtr->firstCylinder;
domainPtr->numCylinders = diskInfoPtr->numCylinders;
/*
* The device.serverID from the disk is used during boot to discover
* the host"s spriteID if reverse arp couldn't find a host ID. The
* unit number of disk indicates what partition of the disk this
* domain header applies to. For example, both the "a" and "c" partitions
* typically start at sector zero, but only one is valid. During boot
* time the unit number is used to decide which partition should be
* attached.
*/
domainPtr->device.serverID = spriteID;
domainPtr->device.type = -1;
domainPtr->device.unit = partition;
domainPtr->device.data = (ClientData)-1;
geoPtr = &domainPtr->geometry;
SetDiskGeometry(&domainPtr->geometry);
SetDomainParts();
}
/*
*----------------------------------------------------------------------
*
* SetDiskGeometry --
*
* This computes the rotational set arrangment depending on the
* disk geometry. The basic rules for this are that filesystem blocks
* are skewed on successive tracks, and that the skewing pattern
* repeats in either 2 or 4 tracks. This is specific to the fact that
* filesystem blocks are 4Kbytes. This means that one disk track
* contains N/4 filesystem blocks and that one sector per track
* is wasted if there are an odd number of sectors per track.
*
* Results:
* None.
*
* Side effects:
* Fill in the geometry struct.
*
*----------------------------------------------------------------------
*/
void
SetDiskGeometry(geoPtr)
register Fsdm_Geometry *geoPtr; /* Fancy geometry information */
{
int index; /* Array index */
int numBlocks; /* The number of blocks in a rotational set */
int tracksPerSet; /* Total number of tracks in a rotational set */
int numTracks; /* The number of tracks in the set so far */
int extraSectors; /* The number of leftover sectors in a track */
int offset; /* The sector offset within a track */
int startingOffset; /* The offset of the first block in a track */
int offsetIncrement; /* The skew of the starting offset on each
* successive track of the rotational set */
Boolean overlap; /* TRUE if filesystem blocks overlap tracks */
geoPtr->numHeads = diskInfoPtr->numHeads;
geoPtr->sectorsPerTrack = diskInfoPtr->numSectors;
/*
* Figure out some basic parameters of the rotational set. The number
* of tracks in the set is either 2 or 4. If 2, then the blocks on
* successive tracks are skewed by 1/2 a filesystem block. If 4,
* blocks are skewed by 1/4 block. A 4 track rotational set is best
* becasue there are more rotational positions. If, however, it
* causes 2 or 3 wasted tracks at the end, or if blocks naturally
* overlap by 1/2 block, then only 2 tracks per rotational set are
* used.
*/
switch(geoPtr->numHeads % 4) {
case 0:
case 1: {
extraSectors = geoPtr->sectorsPerTrack % DISK_SECTORS_PER_BLOCK;
if (extraSectors < DISK_SECTORS_PER_BLOCK/4) {
/*
* Not enough extra sectors to overlap blocks onto the
* next track. The blocks will fit evenly on a track,
* but the blocks on the following tracks will be skewed.
*/
tracksPerSet = 4;
overlap = FALSE;
offsetIncrement = DISK_SECTORS_PER_BLOCK/4;
} else if (extraSectors < DISK_SECTORS_PER_BLOCK/2) {
/*
* Enough to overlap the first 1/4 block onto the next track.
*/
tracksPerSet = 4;
overlap = TRUE;
offsetIncrement = DISK_SECTORS_PER_BLOCK * 3/4;
} else if (extraSectors < DISK_SECTORS_PER_BLOCK * 3/4) {
/*
* Enough to overlap 1/2 block.
*/
tracksPerSet = 2;
overlap = TRUE;
offsetIncrement = DISK_SECTORS_PER_BLOCK/2;
} else {
/*
* Enough to overlap 3/4 block.
*/
tracksPerSet = 4;
overlap = TRUE;
offsetIncrement = DISK_SECTORS_PER_BLOCK/4;
}
break;
}
case 2:
case 3: {
/*
* Instead of wasting 2 or 3 tracks to have a 4 track rotational
* set, the rotational set is only 2 tracks long. Also see if
* the blocks naturally overlap by 1/2 block.
*/
tracksPerSet = 2;
offsetIncrement = DISK_SECTORS_PER_BLOCK/2;
if ((geoPtr->sectorsPerTrack % DISK_SECTORS_PER_BLOCK) <
DISK_SECTORS_PER_BLOCK/2) {
overlap = FALSE;
} else {
overlap = TRUE;
}
}
}
if (!overlapBlocks) {
overlap = FALSE;
offsetIncrement = 0;
}
printf("overlap %s, offsetIncrement %d\n", (overlap ? "TRUE" : "FALSE"),
offsetIncrement);
/*
* Determine rotational position of the blocks in the rotational set.
*/
extraSectors = geoPtr->sectorsPerTrack;
startingOffset = 0;
offset = startingOffset;
for (numBlocks = 0, numTracks = 0 ; ; ) {
if (extraSectors >= DISK_SECTORS_PER_BLOCK) {
/*
* Ok to fit in another filesystem block on this track.
*/
geoPtr->blockOffset[numBlocks] = offset;
numBlocks++;
offset += DISK_SECTORS_PER_BLOCK;
extraSectors -= DISK_SECTORS_PER_BLOCK;
} else {
/*
* The current block has to take up room on the next track.
*/
numTracks++;
if (numTracks < tracksPerSet) {
/*
* Ok to go to the next track.
*/
startingOffset += offsetIncrement;
if (overlap) {
/*
* If the current block can overlap to the next track,
* use the current offset. Because of the overlap
* there are fewer sectors available for blocks on
* the next track.
*/
geoPtr->blockOffset[numBlocks] = offset;
numBlocks++;
extraSectors = geoPtr->sectorsPerTrack - startingOffset;
}
offset = startingOffset + numTracks * geoPtr->sectorsPerTrack;
if (!overlap) {
/*
* If no overlap the whole next track is available.
*/
extraSectors = geoPtr->sectorsPerTrack;
}
} else {
/*
* Done.
*/
for (index = numBlocks; index < FSDM_MAX_ROT_POSITIONS; index++){
geoPtr->blockOffset[index] = -1;
}
break;
}
}
}
geoPtr->blocksPerRotSet = numBlocks;
geoPtr->tracksPerRotSet = tracksPerSet;
geoPtr->rotSetsPerCyl = geoPtr->numHeads / tracksPerSet;
geoPtr->blocksPerCylinder = numBlocks * geoPtr->rotSetsPerCyl;
/*
* Now the rotational positions have to be sorted so that rotationally
* optimal blocks can be found. The array sortedOffsets is set so
* that the I'th element has the index into blockOffset which contains
* the I'th rotational position, eg.
* blockOffset sortedOffsets
* 0 (+0) 0
* 8 (+0) 2
* 4 (+17) 1
* 12 (+17) 3
*/
offsetIncrement = DISK_SECTORS_PER_BLOCK / tracksPerSet;
for (index = 0 ; index < FSDM_MAX_ROT_POSITIONS ; index++) {
geoPtr->sortedOffsets[index] = -1;
}
for (index = 0 ; index < numBlocks ; index++) {
offset = geoPtr->blockOffset[index] % geoPtr->sectorsPerTrack;
geoPtr->sortedOffsets[offset/offsetIncrement] = index;
}
}
/*
*----------------------------------------------------------------------
*
* SetDomainParts --
*
* Set up the way the domain is divided into 4 areas: the bitmap
* for the file descriptors, the file descriptors, the bitmap for
* the data blocks, and the data blocks.
*
* Results:
* The geometry information is completed.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
void
SetDomainParts()
{
register Fsdm_Geometry *geoPtr;
int numFiles;
int numBlocks;
int offset;
int numSectors;
int numSets;
int bitmapBytes;
/*
* Set aside a number of blocks at the begining of the partition for
* things like the super block, the boot program, and the domain header.
* It is easiest to do this by reserving one or more rotational sets.
*/
geoPtr = &domainPtr->geometry;
numSectors = geoPtr->tracksPerRotSet * geoPtr->sectorsPerTrack;
for ( numSets = 1; ; numSets++ ) {
if (numSets * numSectors >
diskInfoPtr->domainSector + diskInfoPtr->numDomainSectors) {
break;
}
}
printf("Reserving %d blocks for domain header, etc.\n",
numSets*geoPtr->blocksPerRotSet);
/*
* Determine the number of filesystem blocks available and compute a
* first guess at the number of file descriptors. If at the end of
* the computation things don't fit nicely, then the number of files
* is changed and the computation is repeated.
*/
numFiles = 0;
do {
numBlocks = geoPtr->blocksPerCylinder * diskInfoPtr->numCylinders -
numSets * geoPtr->blocksPerRotSet;
if (numFiles == 0) {
numFiles = numBlocks * DISK_KBYTES_PER_BLOCK / kbytesToFileDesc;
}
numFiles &= ~(FSDM_FILE_DESC_PER_BLOCK-1);
offset = numSets * geoPtr->blocksPerRotSet;
domainPtr->fdBitmapOffset = offset;
bitmapBytes = (numFiles - 1) / BITS_PER_BYTE + 1;
domainPtr->fdBitmapBlocks = (bitmapBytes - 1) / FS_BLOCK_SIZE + 1;
numBlocks -= domainPtr->fdBitmapBlocks;
offset += domainPtr->fdBitmapBlocks;
domainPtr->fileDescOffset = offset;
domainPtr->numFileDesc = numFiles;
numBlocks -= numFiles / FSDM_FILE_DESC_PER_BLOCK;
offset += numFiles / FSDM_FILE_DESC_PER_BLOCK;
/*
* The data blocks will start on a cylinder. Try the next
* cylinder boundary after the start of the bitmap.
*/
domainPtr->bitmapOffset = offset;
domainPtr->dataOffset = ((offset-1) / geoPtr->blocksPerCylinder + 1)
* geoPtr->blocksPerCylinder;
domainPtr->dataBlocks = domainPtr->numCylinders *
geoPtr->blocksPerCylinder -
domainPtr->dataOffset;
bitmapBytes = (domainPtr->dataBlocks * DISK_KBYTES_PER_BLOCK -
1) / BITS_PER_BYTE + 1;
domainPtr->bitmapBlocks = (bitmapBytes - 1) / FS_BLOCK_SIZE + 1;
/*
* Check the size of the bit map against space available for it
* between the end of the file descriptors and the start of the
* data blocks.
*/
if (domainPtr->dataOffset - domainPtr->bitmapOffset <
domainPtr->bitmapBlocks) {
int numBlocksNeeded;
/*
* Need more blocks to hold the bitmap. Reduce the number
* of file descriptors to get the blocks and re-iterate.
*/
numBlocksNeeded = domainPtr->bitmapBlocks -
(domainPtr->dataOffset - domainPtr->bitmapOffset);
numFiles -= numBlocksNeeded * FSDM_FILE_DESC_PER_BLOCK;
} else if (domainPtr->dataOffset - domainPtr->bitmapOffset >
domainPtr->bitmapBlocks) {
int extraBlocks;
/*
* There are extra blocks between the end of the file descriptors
* and the start of the bitmap. Increase the number of
* file descriptors and re-iterate.
*/
extraBlocks = domainPtr->dataOffset - domainPtr->bitmapOffset -
domainPtr->bitmapBlocks;
numFiles += extraBlocks * FSDM_FILE_DESC_PER_BLOCK;
}
} while (domainPtr->dataOffset - domainPtr->bitmapOffset !=
domainPtr->bitmapBlocks);
domainPtr->dataCylinders = domainPtr->dataBlocks /
geoPtr->blocksPerCylinder ;
}
/*
*----------------------------------------------------------------------
*
* SetSummaryInfo --
*
* Initialize the summary information for the domain. It is well
* known that this occupies one sector.
*
* Results:
* A return code.
*
* Side effects:
* Fill in the summary info.
*
*----------------------------------------------------------------------
*/
void
SetSummaryInfo()
{
bzero((Address)summaryPtr, DEV_BYTES_PER_SECTOR);
strcpy(summaryPtr->domainPrefix, "(new domain)");
/*
* 4 blocks are already allocated for the root directory.
*/
summaryPtr->numFreeKbytes = domainPtr->dataBlocks * (FS_BLOCK_SIZE / 1024)
- 4;
/*
* 3 file descriptors are already used, 0 and 1 are reserved and
* 2 is for the root.
*/
summaryPtr->numFreeFileDesc = domainPtr->numFileDesc - 3;
/*
* The summary state field is unused.
*/
summaryPtr->state = 0;
/*
* The domain number under which this disk partition is mounted is
* recorded on disk so servers re-attach disks under the same "name".
* We set it to the special value so it gets a new number assigned
* when it is first attached.
*/
summaryPtr->domainNumber = -1;
/*
* The flags field is used to record whether or not the disk has been
* safely "sync"ed to disk upon shutdown.
*/
summaryPtr->flags = 0;
summaryPtr->attachSeconds = 0;
summaryPtr->detachSeconds = 0;
summaryPtr->fixCount = 0;
}
/*
*----------------------------------------------------------------------
*
* WriteAllFileDescs --
*
* Write out the file descriptor array to disk.
*
* Results:
* None.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
void
WriteAllFileDescs()
{
int status;
char *bitmap;
char *block;
register Fsdm_FileDescriptor *fileDescPtr;
register int index;
bitmap = MakeFileDescBitmap();
if (!printOnly) {
status = Disk_BlockWrite(partFID, domainPtr,
domainPtr->fdBitmapOffset,
domainPtr->fdBitmapBlocks, (Address)bitmap);
if (status != 0) {
fprintf(stderr, "WriteAllFileDescs: Could write fd bitmap\n");
exit(1);
}
}
/*
* Make the first block of file descriptors. This contains some
* canned file descriptors for the root, bad block file, and the
* lost and found directory. For (early system) testing an empty file
* can also be created.
*/
block = (char *)malloc(FS_BLOCK_SIZE);
bzero(block, FS_BLOCK_SIZE);
for (index = 0;
index < FSDM_FILE_DESC_PER_BLOCK;
index++ ) {
fileDescPtr = (Fsdm_FileDescriptor *)((int)block +
index * FSDM_MAX_FILE_DESC_SIZE);
fileDescPtr->magic = FSDM_FD_MAGIC;
if (index < FSDM_BAD_BLOCK_FILE_NUMBER) {
fileDescPtr->flags = FSDM_FD_RESERVED;
} else if (index == FSDM_BAD_BLOCK_FILE_NUMBER) {
InitDesc(fileDescPtr, FS_FILE, 0, -1, -1, 0, 0, 0700, curTime.tv_sec);
fileDescPtr->permissions = 0000;
fileDescPtr->numLinks = 0;
} else if (index == FSDM_ROOT_FILE_NUMBER) {
InitDesc(fileDescPtr, FS_DIRECTORY, FS_BLOCK_SIZE, -1, -1, 0,
0, 0755, curTime.tv_sec);
/*
* Place the data in the first file system block.
*/
fileDescPtr->direct[0] = 0;
} else {
fileDescPtr->flags = FSDM_FD_FREE;
}
}
if (!printOnly) {
/*
* Write out the first, specially hand crafted, block of file
* descriptors.
*/
status = Disk_BlockWrite(partFID, domainPtr,
domainPtr->fileDescOffset,
1, (Address)block);
if (status != 0) {
fprintf(stderr, "WriteAllFileDescs: Couldn't write descriptor\n");
exit(1);
}
/*
* Redo the block for the remaining file descriptors
*/
bzero(block, FS_BLOCK_SIZE);
for (index = 0;
index < FSDM_FILE_DESC_PER_BLOCK;
index++ ) {
fileDescPtr = (Fsdm_FileDescriptor *)((int)block + index *
FSDM_MAX_FILE_DESC_SIZE);
fileDescPtr->magic = FSDM_FD_MAGIC;
fileDescPtr->flags = FSDM_FD_FREE;
}
/*
* Write out the remaining file descriptors.
*/
for (index = FSDM_FILE_DESC_PER_BLOCK;
index < domainPtr->numFileDesc;
index += FSDM_FILE_DESC_PER_BLOCK) {
status = Disk_BlockWrite(partFID, domainPtr,
domainPtr->fileDescOffset + (index/FSDM_FILE_DESC_PER_BLOCK),
1, (Address)block);
if (status != 0) {
fprintf(stderr,
"WriteAllFileDescs: Couldn't write descriptor (2)\n");
exit(1);
}
}
}
}
/*
*----------------------------------------------------------------------
*
* MakeFileDescBitmap --
*
* Compute out the bitmap for file descriptor array to disk.
*
* Results:
* None.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
char *
MakeFileDescBitmap()
{
register char *bitmap;
register int index;
/*
* Allocate and initialize the bitmap to all 0"s to mean all free.
*/
bitmap = (char *)malloc((unsigned) domainPtr->fdBitmapBlocks *
FS_BLOCK_SIZE);
bzero((Address)bitmap, domainPtr->fdBitmapBlocks * FS_BLOCK_SIZE);
/*
* Reserve file descriptors 0, 1, and 2. File number 0 is not used at
* all in the filesystem. File number 1 is for the file with bad blocks.
* File number 2 (FSDM_ROOT_FILE_NUMBER) is the root directory of the domain.
*
* IF THIS CHANGES remember to fix SetSummaryInfo
*/
bitmap[0] |= 0xe0;
/*
* Set the bits in the map at the end that don't correspond to
* any existing file descriptors.
*/
index = domainPtr->numFileDesc / BITS_PER_BYTE;
if (domainPtr->numFileDesc % BITS_PER_BYTE) {
register int bitIndex;
/*
* Take care the last byte that only has part of its bits set.
*/
for (bitIndex = domainPtr->numFileDesc % BITS_PER_BYTE;
bitIndex < BITS_PER_BYTE;
bitIndex++) {
bitmap[index] |= 1 << ((BITS_PER_BYTE - 1) - bitIndex);
}
index++;
}
for ( ; index < domainPtr->fdBitmapBlocks * FS_BLOCK_SIZE; index++) {
bitmap[index] = 0xff;
}
if (printOnly) {
Disk_PrintFileDescBitmap(domainPtr, bitmap);
}
return(bitmap);
}
/*
*----------------------------------------------------------------------
*
* WriteAndInitDataBitmap --
*
* Write out the bitmap for the data blocks. This knows that the
* first 4K is allocated to the root directory.
*
* Results:
* A return code from the writes.
*
* Side effects:
* Write the bitmap.
*
*----------------------------------------------------------------------
*/
void
WriteAndInitDataBitmap()
{
int status;
char *bitmap;
int kbytesPerCyl;
int bitmapBytesPerCyl;
int index;
bitmap = (char *)malloc((unsigned) domainPtr->bitmapBlocks * FS_BLOCK_SIZE);
bzero(bitmap, domainPtr->bitmapBlocks * FS_BLOCK_SIZE);
/*
* Set the bit corresponding to the 4K used for the root directory.
* ________
* |0______7| Bits are numbered like this in a byte.
*
* IF THIS CHANGES remember to fix SetSummaryInfo()
*/
bitmap[0] |= 0xf0;
/*
* The bitmap is organized by cylinder. There are whole number of
* bytes in the bitmap for each cylinder. Each bit in the bitmap
* corresponds to 1 kbyte on the disk.
*/
kbytesPerCyl = domainPtr->geometry.blocksPerCylinder * DISK_KBYTES_PER_BLOCK;
bitmapBytesPerCyl = (kbytesPerCyl - 1) / BITS_PER_BYTE + 1;
if ((kbytesPerCyl % BITS_PER_BYTE) != 0) {
/*
* There are bits in the last byte of the bitmap for each cylinder
* that don't have kbytes behind them. Set those bits here so
* the blocks don't get allocated.
*/
register int extraBits;
register int mask;
extraBits = kbytesPerCyl % BITS_PER_BYTE;
/*
* Set up a mask that has the right part filled with 1"s.
*/
mask = 0x0;
for ( ; extraBits < BITS_PER_BYTE ; extraBits++) {
mask |= 1 << ((BITS_PER_BYTE - 1) - extraBits);
}
for (index = 0;
index < domainPtr->dataBlocks * DISK_KBYTES_PER_BLOCK / BITS_PER_BYTE;
index += bitmapBytesPerCyl) {
bitmap[index + bitmapBytesPerCyl - 1] |= mask;
}
}
/*
* Set the bits in the bitmap that correspond to non-existent cylinders;
* the bitmap is allocated a whole number of blocks on the disk
* so there are bytes at its end that don't have blocks behind them.
*/
for (index = domainPtr->dataCylinders * bitmapBytesPerCyl;
index < domainPtr->bitmapBlocks * FS_BLOCK_SIZE;
index++) {
bitmap[index] = 0xff;
}
if (printOnly) {
Disk_PrintDataBlockBitmap(domainPtr, bitmap);
} else {
status = Disk_BlockWrite(partFID, domainPtr,
domainPtr->bitmapOffset,
domainPtr->bitmapBlocks, (Address)bitmap);
if (status != 0) {
fprintf(stderr, "WriteAndInitDataBitmap: Couldn't write bitmap\n");
exit(status);
}
}
}
/*
*----------------------------------------------------------------------
*
* WriteRootDirectory --
*
* Write the data blocks of the root directory.
*
* Results:
* A return code from the writes.
*
* Side effects:
* Write the root directory"s data block.
*
*----------------------------------------------------------------------
*/
void
WriteRootDirectory()
{
int status;
char *block;
Fslcl_DirEntry *dirEntryPtr;
int offset;
int i;
block = (char *)malloc(FS_BLOCK_SIZE);
CreateDir(block, FSDM_ROOT_FILE_NUMBER, FSDM_ROOT_FILE_NUMBER);
if (printOnly) {
printf("Root Directory\n");
offset = 0;
dirEntryPtr = (Fslcl_DirEntry *)block;
Disk_PrintDirEntry(dirEntryPtr);
offset += dirEntryPtr->recordLength;
dirEntryPtr = (Fslcl_DirEntry *)((int)block + offset);
Disk_PrintDirEntry(dirEntryPtr);
} else {
/*
* This write trounces the data beyond the stuff allocated to
* the root directory. Currently this is ok and is done because
* BlockWrite writes whole numbers of filesystem blocks.
*/
status = Disk_BlockWrite(partFID, domainPtr,
domainPtr->dataOffset, 1, block);
if (status != 0) {
fprintf(stderr, "WriteRootDirectory: Couldn't write directory\n");
exit(status);
}
}
}
/*
* The 8 partitions, a through h.
*/
#define A_PART 0
#define B_PART 1
#define C_PART 2
#define D_PART 3
#define E_PART 4
#define F_PART 5
#define G_PART 6
#define H_PART 7
#define BUF_SIZE 100
char buf[BUF_SIZE];
char fullBuf[BUF_SIZE];
/*
*----------------------------------------------------------------------
*
* ScanDiskTab --
*
* Initialize the disk info struct by looking up this disk type in
* the disk table.
*
* Results:
* A pointer to a disk info struct.
*
* Side effects:
* Disk info struct malloc'd and initialized. The disk header will be
* written if is successfully set up.
*
*----------------------------------------------------------------------
*/
Disk_Info *
ScanDiskTab()
{
FILE *fp;
int len;
char *bufPtr;
int fullBufLen;
Fsdm_DiskPartition partTable[FSDM_NUM_DISK_PARTS];
int i;
int sectorsPerTrack;
int tracksPerCylinder;
int sectorsPerCylinder;
int numCylinders;
Disk_Info *diskInfoPtr;
fp = fopen("/etc/disktab", "r");
if (fp == NULL) {
perror("/etc/disktab");
exit(1);
}
len = strlen(diskType);
/*
* Scan until we reach a line that contains the disk type in it.
*/
while (fgets(buf, BUF_SIZE, fp) != NULL) {
if (strncmp(diskType, buf, len) == 0 &&
buf[len] == '|') {
/*
* We found the disk type.
*/
break;
}
}
if (strncmp(diskType, buf, len) != 0) {
fprintf(stderr, "`%s' not in disktab\n", diskType);
exit(1);
}
fullBufLen = 0;
/*
* Now cram all of the lines that end in "\" together.
*/
while (1) {
for (bufPtr = buf; *bufPtr != '\n' && *bufPtr != '\\'; bufPtr++) {
if (*bufPtr != ' ' && *bufPtr != '\t') {
fullBuf[fullBufLen] = *bufPtr;
fullBufLen++;
}
}
if (*bufPtr == '\n') {
fullBuf[fullBufLen] = 0;
break;
}
if (fgets(buf, BUF_SIZE, fp) == NULL) {
fprintf(stderr, "Premature EOF\n");
exit(1);
}
}
/*
* Now build up a partition table.
*/
for (i = 0; i < FSDM_NUM_DISK_PARTS; i++) {
partTable[i].firstCylinder = 0;
partTable[i].numCylinders = 0;
}
for (bufPtr = fullBuf; *bufPtr != 0; bufPtr++) {
int partition;
if (strncmp(bufPtr, ":ns#", 4) == 0) {
bufPtr += 4;
sscanf(bufPtr, "%d", §orsPerTrack);
} else if (strncmp(bufPtr, ":nt#", 4) == 0) {
bufPtr += 4;
sscanf(bufPtr, "%d", &tracksPerCylinder);
} else if (strncmp(bufPtr, ":nc#", 4) == 0) {
bufPtr += 4;
sscanf(bufPtr, "%d", &numCylinders);
} else if (strncmp(bufPtr, ":p", 2) == 0) {
/*
* Skip past the ":p".
*/
bufPtr += 2;
partition = *bufPtr - 'a';
/*
* Skip past the partition character and the #.
*/
bufPtr += 2;
sscanf(bufPtr, "%d", &partTable[partition].numCylinders);
}
}
/*
* Now that we've built up the number of cylinders build up the
* cylinder offsets.
*/
sectorsPerCylinder = sectorsPerTrack * tracksPerCylinder;
for (i = 0; i < FSDM_NUM_DISK_PARTS; i++) {
partTable[i].numCylinders /= sectorsPerCylinder;
}
partTable[A_PART].firstCylinder = 0;
partTable[B_PART].firstCylinder = partTable[A_PART].numCylinders;
partTable[C_PART].firstCylinder = 0;
partTable[D_PART].firstCylinder = partTable[B_PART].firstCylinder +
partTable[B_PART].numCylinders;
partTable[E_PART].firstCylinder = partTable[D_PART].firstCylinder +
partTable[D_PART].numCylinders;
partTable[F_PART].firstCylinder = partTable[E_PART].firstCylinder +
partTable[E_PART].numCylinders;
partTable[F_PART].numCylinders =
numCylinders - (partTable[E_PART].firstCylinder +
partTable[E_PART].numCylinders);
partTable[G_PART].firstCylinder = partTable[B_PART].firstCylinder +
partTable[B_PART].numCylinders;
partTable[G_PART].numCylinders =
numCylinders - (partTable[B_PART].firstCylinder +
partTable[B_PART].numCylinders);
/*
* Print out the partition table.
*/
printf("Sectors-per-track: %d\n", sectorsPerTrack);
printf("Tracks-per-cylinder: %d\n", tracksPerCylinder);
printf("Sectors-per-cylinder: %d\n", sectorsPerCylinder);
printf("Num-cylinders: %d\n\n", numCylinders);
printf("Partition First-Cylinder Num-Cylinders\n");
for (i = 0; i < FSDM_NUM_DISK_PARTS; i++) {
printf("%c %d %d\n",
'a' + i, partTable[i].firstCylinder,
partTable[i].numCylinders);
}
/*
* Set up a disk header and write it to sector 0.
*/
if (!printOnly) {
int *headerPtr;
Fsdm_DiskHeader header;
int checkSum;
int status;
bzero(&header, sizeof(header));
strcpy(header.asciiLabel, diskType);
header.magic = FSDM_DISK_MAGIC;
header.numCylinders = numCylinders;
header.numAltCylinders = 0;
header.numHeads = tracksPerCylinder;
header.numSectors = sectorsPerTrack;
header.bootSector = 1;
header.numBootSectors = 15;
header.summarySector = 17;
header.domainSector = 18;
header.numDomainSectors = FSDM_NUM_DOMAIN_SECTORS;
header.partition = partition;
bcopy(partTable, header.map, sizeof(header.map));
/*
* Compute the checksum.
*/
header.checkSum = FSDM_DISK_MAGIC;
checkSum = 0;
for (i = 0, headerPtr = (int *)&header;
i < DEV_BYTES_PER_SECTOR;
i += sizeof(int), headerPtr++) {
checkSum ^= *headerPtr;
}
header.checkSum = checkSum;
/*
* Recompute the checksum and make sure it matches.
*/
checkSum = 0;
for (i = 0, headerPtr = (int *)&header;
i < DEV_BYTES_PER_SECTOR;
i += sizeof(int), headerPtr++) {
checkSum ^= *headerPtr;
}
if (checkSum != FSDM_DISK_MAGIC) {
fprintf(stderr, "Bad checksum\n");
exit(1);
}
/*
* Write out the disk header. Unless this is a sun.
* On suns the disk label is a special format so the
* prom can read it. So we don't mess with it.
*/
#if !defined(sun) && !defined(sun3) && !defined(sun4)
status = Disk_SectorWrite(partFID, 0, 1, (Address)&header);
if (status != 0) {
perror("Couldn't write out the disk header");
exit(1);
}
#endif
}
/*
* Allocate, initialize and return the disk info struct.
*/
diskInfoPtr = (Disk_Info *)malloc(sizeof(Disk_Info));
(void)strcpy(diskInfoPtr->asciiLabel, diskType);
diskInfoPtr->bootSector = 1;
diskInfoPtr->numBootSectors = 15;
diskInfoPtr->summarySector = 17;
diskInfoPtr->domainSector = 18;
diskInfoPtr->numDomainSectors = FSDM_NUM_DOMAIN_SECTORS;
diskInfoPtr->firstCylinder = partTable[partition].firstCylinder;
diskInfoPtr->numCylinders = partTable[partition].numCylinders;
diskInfoPtr->numHeads = tracksPerCylinder;
diskInfoPtr->numSectors = sectorsPerTrack;
return(diskInfoPtr);
}
/*
*----------------------------------------------------------------------
*
* ReadFileDescBitmap --
*
* Read in the file descriptor bitmap.
*
* Results:
* A pointer to the file descriptor bit map.
*
* Side effects:
* Memory allocated for the bit map.
*
*----------------------------------------------------------------------
*/
unsigned char *
ReadFileDescBitmap()
{
register unsigned char *bitmap;
/*
* Allocate the bitmap.
*/
bitmap = (unsigned char *)malloc(domainPtr->fdBitmapBlocks * FS_BLOCK_SIZE);
if (Disk_BlockRead(partFID, domainPtr, domainPtr->fdBitmapOffset,
domainPtr->fdBitmapBlocks, (Address)bitmap) < 0) {
fprintf(stderr, "ReadFileDescBitmap: Read failed");
exit(1);
}
return(bitmap);
}
/*
*----------------------------------------------------------------------
*
* WriteFileDescBitmap --
*
* Write out the file descriptor bitmap.
*
* Results:
* None.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
void
WriteFileDescBitmap(bitmap)
register unsigned char *bitmap; /* Bitmap to write. */
{
if (Disk_BlockWrite(partFID, domainPtr, domainPtr->fdBitmapOffset,
domainPtr->fdBitmapBlocks, (Address)bitmap) < 0) {
fprintf(stderr, "WriteFileDescBitmap: Write failed");
exit(1);
}
}
/*
*----------------------------------------------------------------------
*
* ReadBitmap --
*
* Read the bitmap off disk.
*
* Results:
* A pointer to the bitmap.
*
* Side effects:
* Memory allocated for the bit map.
*
*----------------------------------------------------------------------
*/
unsigned char *
ReadBitmap()
{
unsigned char *bitmap;
bitmap = (unsigned char *)malloc(domainPtr->bitmapBlocks * FS_BLOCK_SIZE);
if (Disk_BlockRead(partFID, domainPtr, domainPtr->bitmapOffset,
domainPtr->bitmapBlocks, (Address) bitmap) < 0) {
fprintf(stderr, "ReadBitmap: Read failed");
exit(1);
}
return(bitmap);
}
/*
*----------------------------------------------------------------------
*
* WriteBitmap --
*
* Write the bitmap to disk.
*
* Results:
* None.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
void
WriteBitmap(bitmap)
unsigned char *bitmap; /* Bitmap to write. */
{
if (Disk_BlockWrite(partFID, domainPtr, domainPtr->bitmapOffset,
domainPtr->bitmapBlocks, (Address) bitmap) < 0) {
fprintf(stderr, "WriteBitmap: Write failed");
exit(1);
}
}
/*
*----------------------------------------------------------------------
*
* ReadFileDesc --
*
* Return the given file descriptor.
*
* Results:
* None.
*
* Side effects:
* The file descriptor struct is filled in.
*
*----------------------------------------------------------------------
*/
void
ReadFileDesc(fdNum, fdPtr)
int fdNum;
Fsdm_FileDescriptor *fdPtr;
{
static char block[FS_BLOCK_SIZE];
int blockNum;
int offset;
blockNum = domainPtr->fileDescOffset + fdNum / FSDM_FILE_DESC_PER_BLOCK;
offset = (fdNum & (FSDM_FILE_DESC_PER_BLOCK - 1)) * FSDM_MAX_FILE_DESC_SIZE;
if (Disk_BlockRead(partFID, domainPtr, blockNum, 1,
(Address) block) < 0) {
fprintf(stderr, "ReadFileDesc: Read failed\n");
exit(1);
}
bcopy((Address)&block[offset], (Address)fdPtr, sizeof(Fsdm_FileDescriptor));
}
/*
*----------------------------------------------------------------------
*
* WriteFileDesc --
*
* Return the given file descriptor.
*
* Results:
* None.
*
* Side effects:
* The file descriptor struct is filled in.
*
*----------------------------------------------------------------------
*/
void
WriteFileDesc(fdNum, fdPtr)
int fdNum;
Fsdm_FileDescriptor *fdPtr;
{
static char block[FS_BLOCK_SIZE];
int blockNum;
int offset;
blockNum = domainPtr->fileDescOffset + fdNum / FSDM_FILE_DESC_PER_BLOCK;
offset = (fdNum & (FSDM_FILE_DESC_PER_BLOCK - 1)) * FSDM_MAX_FILE_DESC_SIZE;
if (Disk_BlockRead(partFID, domainPtr, blockNum, 1,
(Address) block) < 0) {
fprintf(stderr, "WriteFileDesc: Read failed\n");
exit(1);
}
bcopy(fdPtr, (Address)&block[offset], sizeof(Fsdm_FileDescriptor));
if (Disk_BlockWrite(partFID, domainPtr, blockNum, 1,
(Address) block) < 0) {
fprintf(stderr, "WriteFileDesc: Write failed\n");
exit(1);
}
}
char fileBlock[FS_BLOCK_SIZE];
char indirectBlock[FS_BLOCK_SIZE];
int *indIndexPtr = (int *)indirectBlock;
/*
*----------------------------------------------------------------------
*
* CopyTree --
*
* Copy the tree of files in the given directory
* the disk table.
*
* Results:
* A pointer to a disk info struct.
*
* Side effects:
* Disk info struct malloc'd and initialized. The disk header will be
* written if is successfully set up.
*
*----------------------------------------------------------------------
*/
void
CopyTree(dirName, dirFDNum, dirFDPtr, parentFDNum, createDir, path)
char *dirName; /* Name of directory to copy. */
int dirFDNum; /* File number of directory. */
Fsdm_FileDescriptor *dirFDPtr; /* File descriptor of directory. */
int parentFDNum; /* File number of parent. */
Boolean createDir; /* Should create the directory. */
char *path;
{
DIR *unixDirPtr;
Fslcl_DirEntry *unixDirEntPtr;
DirIndexInfo indexInfo;
Fslcl_DirEntry *spriteDirEntPtr;
char fileName[FS_MAX_NAME_LENGTH + 1];
int newFDNum;
Fsdm_FileDescriptor newFD;
Fsdm_FileDescriptor *newFDPtr;
struct stat statBuf;
int followLinks;
char pathName[1024];
/*
* Get our absolute path name so we can get back if we follow a
* symbolic link.
*/
getwd(pathName);
if (chdir(dirName) < 0) {
perror(dirName);
exit(1);
}
/*
* Get a pointer to the UNIX directory.
*/
unixDirPtr = opendir(".");
if (unixDirPtr == NULL) {
fprintf(stderr, "Can't open directory %s\n", dirName);
exit(1);
}
/*
* Open the Sprite directory.
*/
spriteDirEntPtr = OpenDir(dirFDPtr, &indexInfo);
if (spriteDirEntPtr == (Fslcl_DirEntry *)NULL) {
if (chdir(pathName) < 0) {
perror(pathName);
exit(1);
}
}
/*
* See if there is a "follow.links" file in this directory. If so
* we are supposed to follow symbolic links rather than just copying
* the links.
*/
if (stat("follow.links", &statBuf) < 0) {
followLinks = 0;
} else {
printf("Following links ...\n");
followLinks = 1;
}
if (createDir) {
CreateDir(indexInfo.dirBlock, dirFDNum, parentFDNum);
}
for (unixDirEntPtr = (Fslcl_DirEntry *)readdir(unixDirPtr);
unixDirEntPtr != NULL;
unixDirEntPtr = (Fslcl_DirEntry *)readdir(unixDirPtr)) {
if (unixDirEntPtr->nameLength == 1 &&
strncmp(unixDirEntPtr->fileName, ".", 1) == 0) {
continue;
}
if (unixDirEntPtr->nameLength == 2 &&
strncmp(unixDirEntPtr->fileName, "..", 2) == 0) {
continue;
}
strncpy(fileName, unixDirEntPtr->fileName, unixDirEntPtr->nameLength);
fileName[unixDirEntPtr->nameLength] = 0;
if (followLinks) {
if (stat(fileName, &statBuf) < 0) {
perror(fileName);
exit(1);
}
} else {
if (lstat(fileName, &statBuf) < 0) {
perror(fileName);
exit(1);
}
}
newFDNum = freeFDNum;
freeFDNum++;
MarkFDBitmap(newFDNum, fdBitmapPtr);
summaryPtr->numFreeFileDesc--;
/*
* Read out the file descriptor being careful to save it around
* if we found the /dev descriptor.
*/
if ((strcmp(fileName, "dev") == 0) &&
(dirFDNum == FSDM_ROOT_FILE_NUMBER)) {
if (!(statBuf.st_mode & S_GFDIR)) {
fprintf(stderr, "dev isn't a directory\n");
exit(1);
}
ReadFileDesc(newFDNum, &devFD);
newFDPtr = &devFD;
devFDNum = newFDNum;
devFDPtr = newFDPtr;
} else {
ReadFileDesc(newFDNum, &newFD);
newFDPtr = &newFD;
}
spriteDirEntPtr = AddToDirectory(&indexInfo, spriteDirEntPtr,
newFDNum, fileName);
if (statBuf.st_mode & S_GFDIR) {
char newPath[FS_MAX_NAME_LENGTH];
/*
* Increment the current directories link count because once
* the child gets created it will point to the parent.
*/
dirFDPtr->numLinks++;
/*
* Allocate the currently free file descriptor to this directory.
*/
InitDesc(newFDPtr, FS_DIRECTORY, FS_BLOCK_SIZE, -1, -1,
0, 0, statBuf.st_mode & 07777, statBuf.st_mtime);
/*
* Give the directory one full block. The directory will
* be initialized by CopyTree when we call it recursively.
*/
newFDPtr->direct[0] = freeBlockNum * FS_FRAGMENTS_PER_BLOCK;
MarkDataBitmap(domainPtr, cylBitmapPtr, freeBlockNum,
FS_FRAGMENTS_PER_BLOCK);
freeBlockNum++;
sprintf(newPath, "%s%s/", path, fileName);
printf("Directory: %s\n", newPath);
CopyTree(fileName, newFDNum, newFDPtr, dirFDNum, TRUE, newPath);
} else if ((statBuf.st_mode & S_GFMT) == S_GFREG ||
(statBuf.st_mode & S_GFMT) == S_GFLNK) {
int fd;
int blockNum;
int toRead;
int len;
blockNum = 0;
if ((statBuf.st_mode & S_GFMT) == S_GFREG) {
printf("File: %s%s\n", path, fileName);
InitDesc(newFDPtr, FS_FILE, statBuf.st_size, -1, -1,
0, 0, statBuf.st_mode & 07777, statBuf.st_mtime);
/*
* Copy the file over.
*/
fd = open(fileName, 0);
if (fd < 0) {
perror(fileName);
exit(1);
}
len = read(fd, fileBlock, FS_BLOCK_SIZE);
if (len < 0) {
perror(fileName);
exit(1);
}
toRead = statBuf.st_size;
} else {
len = readlink(fileName, fileBlock, FS_BLOCK_SIZE);
if (len < 0) {
perror(fileName);
exit(1);
}
fileBlock[len] = '\0';
InitDesc(newFDPtr, FS_SYMBOLIC_LINK, len + 1, -1, -1,
0, 0, 0777, statBuf.st_mtime);
printf("Symbolic link: %s%s -> %s\n",
path, fileName, fileBlock);
toRead = len + 1;
}
while (len > 0) {
if (blockNum == FSDM_NUM_DIRECT_BLOCKS) {
int i;
int *intPtr;
/*
* Must allocate an indirect block.
*/
newFDPtr->indirect[0] =
VirtToPhys(freeBlockNum * FS_FRAGMENTS_PER_BLOCK);
MarkDataBitmap(domainPtr, cylBitmapPtr, freeBlockNum,
FS_FRAGMENTS_PER_BLOCK);
freeBlockNum++;
summaryPtr->numFreeKbytes -= FS_FRAGMENTS_PER_BLOCK;
for (i = 0, intPtr = (int *)indirectBlock;
i < FS_BLOCK_SIZE / sizeof(int);
i++, intPtr++) {
*intPtr = FSDM_NIL_INDEX;
}
}
if (blockNum >= FSDM_NUM_DIRECT_BLOCKS) {
indIndexPtr[blockNum - FSDM_NUM_DIRECT_BLOCKS] =
freeBlockNum * FS_FRAGMENTS_PER_BLOCK;
MarkDataBitmap(domainPtr, cylBitmapPtr, freeBlockNum,
FS_FRAGMENTS_PER_BLOCK);
summaryPtr->numFreeKbytes -= FS_FRAGMENTS_PER_BLOCK;
} else {
newFDPtr->direct[blockNum] =
freeBlockNum * FS_FRAGMENTS_PER_BLOCK;
if (toRead > FS_BLOCK_SIZE) {
MarkDataBitmap(domainPtr, cylBitmapPtr, freeBlockNum,
FS_FRAGMENTS_PER_BLOCK);
summaryPtr->numFreeKbytes -= FS_FRAGMENTS_PER_BLOCK;
} else {
MarkDataBitmap(domainPtr, cylBitmapPtr, freeBlockNum,
(toRead - 1) / FS_FRAGMENT_SIZE + 1);
summaryPtr->numFreeKbytes -=
(toRead - 1) / FS_FRAGMENT_SIZE + 1;
}
}
/*
* Write the block out to disk.
*/
if (Disk_BlockWrite(partFID, domainPtr,
domainPtr->dataOffset + freeBlockNum,
1, (Address)fileBlock) != 0) {
fprintf(stderr, "Couldn't write file block\n");
exit(1);
}
blockNum++;
freeBlockNum++;
if ((statBuf.st_mode & S_GFMT) == S_GFLNK) {
break;
}
toRead -= len;
len = read(fd, fileBlock, FS_BLOCK_SIZE);
if (len < 0) {
perror(fileName);
exit(1);
}
}
if (newFDPtr->indirect[0] != FSDM_NIL_INDEX) {
if (Disk_BlockWrite(partFID, domainPtr,
newFDPtr->indirect[0] / FS_FRAGMENTS_PER_BLOCK,
1, (Address)indirectBlock) != 0) {
fprintf(stderr, "Couldn't write indirect block\n");
exit(1);
}
}
close(fd);
} else {
fprintf(stderr, "Non file or directory\n");
exit(1);
}
WriteFileDesc(newFDNum, newFDPtr);
if (spriteDirEntPtr == (Fslcl_DirEntry *)NULL) {
fprintf(stderr, "%s is full\n", dirName);
break;
}
}
CloseDir(&indexInfo);
if (chdir(pathName) < 0) {
perror(pathName);
exit(1);
}
closedir(unixDirPtr);
return;
}
/*
*----------------------------------------------------------------------
*
* OpenDir --
*
* Set up the structure to allow moving through the given directory.
*
* Results:
* None.
*
* Side effects:
* The index structure is set up and *dirEntryPtrPtr set to point to
* the first directory entry.
*
*----------------------------------------------------------------------
*/
static Fslcl_DirEntry *
OpenDir(fdPtr, indexInfoPtr)
Fsdm_FileDescriptor *fdPtr; /* The file descriptor for the
* directory. */
DirIndexInfo *indexInfoPtr; /* Index info struct */
{
int fragsToRead;
if (fdPtr->lastByte == -1) {
/*
* Empty directory.
*/
return((Fslcl_DirEntry *) NULL);
} else if ((fdPtr->lastByte + 1) % FSLCL_DIR_BLOCK_SIZE != 0) {
fprintf(stderr, "Directory not multiple of directory block size.\n");
exit(1);
} else if (fdPtr->fileType != FS_DIRECTORY) {
fprintf(stderr, "OpenDir: Not a directory\n");
return((Fslcl_DirEntry *)NULL);
}
/*
* Initialize the index structure.
*/
indexInfoPtr->fdPtr = fdPtr;
indexInfoPtr->blockNum = 0;
indexInfoPtr->blockAddr = fdPtr->direct[0] / FS_FRAGMENTS_PER_BLOCK +
domainPtr->dataOffset;
/*
* Read in the directory block.
*/
if (fdPtr->lastByte != FS_BLOCK_SIZE - 1) {
fprintf(stderr, "We created a directory that's not 4K?\n");
exit(1);
}
if (Disk_BlockRead(partFID, domainPtr,
indexInfoPtr->blockAddr,
1, indexInfoPtr->dirBlock) < 0) {
fprintf(stderr, "OpenDir: Read failed block %d\n",
indexInfoPtr->blockAddr);
exit(1);
}
indexInfoPtr->dirOffset = 0;
return((Fslcl_DirEntry *) indexInfoPtr->dirBlock);
}
/*
*----------------------------------------------------------------------
*
* NextDirEntry --
*
* Return a pointer to the next directory entry.
*
* Results:
* None.
*
* Side effects:
* The index structure is modified and *dirEntryPtrPtr set to point
* to the next directory entry.
*
*----------------------------------------------------------------------
*/
Fslcl_DirEntry *
NextDirEntry(indexInfoPtr, dirEntryPtr)
DirIndexInfo *indexInfoPtr;
Fslcl_DirEntry *dirEntryPtr;
{
indexInfoPtr->dirOffset += dirEntryPtr->recordLength;
if (indexInfoPtr->dirOffset < FS_BLOCK_SIZE) {
/*
* The next directory entry is in the current block.
*/
return((Fslcl_DirEntry *)
&(indexInfoPtr->dirBlock[indexInfoPtr->dirOffset]));
} else {
Fsdm_FileDescriptor *fdPtr;
int i;
printf("Adding new block to directory ...\n");
/*
* Write out the current block and set up the next one.
*/
if (!printOnly) {
if (Disk_BlockWrite(partFID, domainPtr, indexInfoPtr->blockAddr,
1, indexInfoPtr->dirBlock) < 0) {
fprintf(stderr, "NextDirEntry: Write failed block %d\n",
indexInfoPtr->blockAddr);
exit(1);
}
}
fdPtr = indexInfoPtr->fdPtr;
fdPtr->lastByte += FS_BLOCK_SIZE;
fdPtr->numKbytes += FS_FRAGMENTS_PER_BLOCK;
indexInfoPtr->blockNum++;
fdPtr->direct[indexInfoPtr->blockNum] =
freeBlockNum * FS_FRAGMENTS_PER_BLOCK;
MarkDataBitmap(domainPtr, cylBitmapPtr, freeBlockNum,
FS_FRAGMENTS_PER_BLOCK);
indexInfoPtr->blockAddr = freeBlockNum + domainPtr->dataOffset;
freeBlockNum++;
for (i = 0, dirEntryPtr = (Fslcl_DirEntry *)indexInfoPtr->dirBlock;
i < FS_BLOCK_SIZE / FSLCL_DIR_BLOCK_SIZE;
i++,dirEntryPtr=(Fslcl_DirEntry *)((unsigned)dirEntryPtr+FSLCL_DIR_BLOCK_SIZE)) {
dirEntryPtr->fileNumber = 0;
dirEntryPtr->recordLength = FSLCL_DIR_BLOCK_SIZE;
dirEntryPtr->nameLength = 0;
}
indexInfoPtr->dirOffset = 0;
return((Fslcl_DirEntry *) indexInfoPtr->dirBlock);
}
}
/*
*----------------------------------------------------------------------
*
* CloseDir --
*
* Flushes the current directory block to disk, if necessary.
*
* Results:
* None.
*
* Side effects:
* The index structure is modified and *dirEntryPtrPtr set to point
* to the next directory entry.
*
*----------------------------------------------------------------------
*/
static void
CloseDir(indexInfoPtr)
DirIndexInfo *indexInfoPtr;
{
if (!printOnly) {
if (Disk_BlockWrite(partFID, domainPtr, indexInfoPtr->blockAddr,
1, indexInfoPtr->dirBlock) < 0) {
fprintf(stderr, "CloseDir: Write (2) failed block %d\n",
indexInfoPtr->blockAddr);
exit(1);
}
}
}
/*
*----------------------------------------------------------------------
*
* InitDesc --
*
* Set up a file descriptor as allocated.
*
* Results:
* None.
*
* Side effects:
* File descriptor fields filled in.
*
*----------------------------------------------------------------------
*/
void
InitDesc(fileDescPtr, fileType, numBytes, devType, devUnit, uid,
gid, permissions, time)
Fsdm_FileDescriptor *fileDescPtr;
int fileType;
int numBytes;
int devType;
int devUnit;
int uid;
int gid;
int permissions;
int time;
{
int index;
fileDescPtr->flags = FSDM_FD_ALLOC;
fileDescPtr->fileType = fileType;
fileDescPtr->permissions = permissions;
fileDescPtr->uid = uid;
fileDescPtr->gid = gid;
fileDescPtr->lastByte = numBytes - 1;
fileDescPtr->firstByte = -1;
if (fileType == FS_DIRECTORY) {
fileDescPtr->numLinks = 2;
} else {
fileDescPtr->numLinks = 1;
}
/*
* Can't know device information because that depends on
* the way the system is configured.
*/
fileDescPtr->devServerID = -1;
fileDescPtr->devType = devType;
fileDescPtr->devUnit = devUnit;
/*
* Set the time stamps. This assumes that universal time,
* not local time, is used for time stamps.
*/
fileDescPtr->createTime = time;
fileDescPtr->accessTime = 0;
fileDescPtr->descModifyTime = time;
fileDescPtr->dataModifyTime = time;
/*
* Place the data in the first filesystem block.
*/
for (index = 0; index < FSDM_NUM_DIRECT_BLOCKS ; index++) {
fileDescPtr->direct[index] = FSDM_NIL_INDEX;
}
for (index = 0; index < FSDM_NUM_INDIRECT_BLOCKS ; index++) {
fileDescPtr->indirect[index] = FSDM_NIL_INDEX;
}
if (numBytes > 0) {
int numBlocks;
numBlocks = (numBytes - 1) / FS_BLOCK_SIZE + 1;
if (numBlocks > FSDM_NUM_DIRECT_BLOCKS) {
fileDescPtr->numKbytes = (numBlocks + 1) * (FS_BLOCK_SIZE / 1024);
} else {
fileDescPtr->numKbytes = (numBytes + 1023) / 1024;
}
} else {
fileDescPtr->numKbytes = 0;
}
fileDescPtr->version = 1;
}
int fragMasks[FS_FRAGMENTS_PER_BLOCK + 1] = {0x0, 0x08, 0x0c, 0x0e, 0x0f};
/*
*----------------------------------------------------------------------
*
* MarkDataBitmap --
*
* Mark the appropriate bits in the data block bitmap.
*
* Results:
* None.
*
* Side effects:
* Data block marked.
*
*----------------------------------------------------------------------
*/
void
MarkDataBitmap(domainPtr, cylBitmapPtr, blockNum, numFrags)
Fsdm_DomainHeader *domainPtr;
unsigned char *cylBitmapPtr;
int blockNum;
int numFrags;
{
unsigned char *bitmapPtr;
bitmapPtr = GetBitmapPtr(domainPtr, cylBitmapPtr, blockNum);
if ((blockNum % domainPtr->geometry.blocksPerCylinder) & 0x1) {
*bitmapPtr |= fragMasks[numFrags];
} else {
*bitmapPtr |= fragMasks[numFrags] << 4;
}
}
/*
*----------------------------------------------------------------------
*
* CreateDir --
*
* Create a directory out of a single file system block.
*
* Results:
* None.
*
* Side effects:
* File system block set up as a directory.
*
*----------------------------------------------------------------------
*/
void
CreateDir(block, dot, dotDot)
Address block; /* Block to create directory in. */
int dot; /* File number of directory. */
int dotDot; /* File number of parent. */
{
Fslcl_DirEntry *dirEntryPtr;
char *fileName;
int offset;
int length;
int i;
dirEntryPtr = (Fslcl_DirEntry *)block;
fileName = ".";
length = strlen(fileName);
dirEntryPtr->fileNumber = dot;
dirEntryPtr->recordLength = Fslcl_DirRecLength(length);
dirEntryPtr->nameLength = length;
strcpy(dirEntryPtr->fileName, fileName);
offset = dirEntryPtr->recordLength;
dirEntryPtr = (Fslcl_DirEntry *)((int)block + offset);
fileName = "..";
length = strlen(fileName);
dirEntryPtr->fileNumber = dotDot;
dirEntryPtr->recordLength = FSLCL_DIR_BLOCK_SIZE - offset;
dirEntryPtr->nameLength = length;
strcpy(dirEntryPtr->fileName, fileName);
/*
* Fill out the rest of the directory with empty blocks.
*/
for (dirEntryPtr = (Fslcl_DirEntry *)&block[FSLCL_DIR_BLOCK_SIZE], i = 1;
i < FS_BLOCK_SIZE / FSLCL_DIR_BLOCK_SIZE;
i++,dirEntryPtr=(Fslcl_DirEntry *)((int)dirEntryPtr + FSLCL_DIR_BLOCK_SIZE)) {
dirEntryPtr->fileNumber = 0;
dirEntryPtr->recordLength = FSLCL_DIR_BLOCK_SIZE;
dirEntryPtr->nameLength = 0;
}
}
/*
*----------------------------------------------------------------------
*
* AddToDirectory --
*
* Add the file descriptor to a directory.
*
* Results:
* None.
*
* Side effects:
* The directory is modified to contain the orphaned file.
*
*----------------------------------------------------------------------
*/
Fslcl_DirEntry *
AddToDirectory(dirIndexPtr, dirEntryPtr, fileNumber, fileName)
DirIndexInfo *dirIndexPtr;
Fslcl_DirEntry *dirEntryPtr;
int fileNumber;
char *fileName;
{
int nameLength;
int recordLength;
int leftOver;
int oldRecLength;
nameLength = strlen(fileName);
recordLength = Fslcl_DirRecLength(nameLength);
while (dirEntryPtr != (Fslcl_DirEntry *) NULL) {
if (dirEntryPtr->fileNumber != 0) {
oldRecLength = Fslcl_DirRecLength(dirEntryPtr->nameLength);
leftOver = dirEntryPtr->recordLength - oldRecLength;
if (leftOver >= recordLength) {
dirEntryPtr->recordLength = oldRecLength;
dirEntryPtr =
(Fslcl_DirEntry *) ((int) dirEntryPtr + oldRecLength);
dirEntryPtr->recordLength = leftOver;
dirIndexPtr->dirOffset += oldRecLength;
} else {
dirEntryPtr = NextDirEntry(dirIndexPtr, dirEntryPtr);
continue;
}
} else if (dirEntryPtr->recordLength < recordLength) {
dirEntryPtr = NextDirEntry(dirIndexPtr, dirEntryPtr);
continue;
}
dirEntryPtr->fileNumber = fileNumber;
dirEntryPtr->nameLength = nameLength;
(void)strcpy(dirEntryPtr->fileName, fileName);
leftOver = dirEntryPtr->recordLength - recordLength;
if (leftOver > FSLCL_DIR_ENTRY_HEADER) {
dirEntryPtr->recordLength = recordLength;
dirEntryPtr =(Fslcl_DirEntry *) ((int) dirEntryPtr + recordLength);
dirEntryPtr->fileNumber = 0;
dirEntryPtr->recordLength = leftOver;
dirIndexPtr->dirOffset += recordLength;
} else {
dirEntryPtr = NextDirEntry(dirIndexPtr, dirEntryPtr);
}
return(dirEntryPtr);
}
fprintf(stderr, "Directory full.\n");
exit(1);
}
/*
*----------------------------------------------------------------------
*
* MakeDevices --
*
* Add devices to the dev directory.
*
* Results:
* None.
*
* Side effects:
* Devices added to the dev directory.
*
*----------------------------------------------------------------------
*/
void
MakeDevices()
{
FILE *fp;
Fslcl_DirEntry *dirEntryPtr;
DirIndexInfo indexInfo;
char fileName[FS_MAX_NAME_LENGTH];
int devType;
int devUnit;
int devPermissions;
char buf[FS_MAX_NAME_LENGTH];
Fsdm_FileDescriptor fileFD;
fp = fopen(devFileName, "r");
if (fp == NULL) {
perror(devFileName);
exit(1);
}
dirEntryPtr = OpenDir(devFDPtr, &indexInfo);
if (dirEntryPtr == (Fslcl_DirEntry *)NULL) {
fprintf(stderr, "MakeDevices: Dev is bogus\n");
exit(1);
}
while (fgets(buf, FS_MAX_NAME_LENGTH, fp) != NULL) {
if (sscanf(buf, "%s %d %d %o", fileName, &devType, &devUnit,
&devPermissions) != 4) {
continue;
}
MarkFDBitmap(freeFDNum, fdBitmapPtr);
ReadFileDesc(freeFDNum, &fileFD);
InitDesc(&fileFD, FS_DEVICE, 0, devType, devUnit, 0, 0,
devPermissions, curTime.tv_sec);
dirEntryPtr = AddToDirectory(&indexInfo, dirEntryPtr, freeFDNum,
fileName);
if (!printOnly) {
WriteFileDesc(freeFDNum, &fileFD);
}
printf("Device: %s, %d, %d 0%o\n",
fileName, devType, devUnit, devPermissions);
summaryPtr->numFreeFileDesc--;
freeFDNum++;
if (dirEntryPtr == (Fslcl_DirEntry *)NULL) {
fprintf(stderr, "MakeDevices: dev directory is full\n");
break;
}
}
CloseDir(&indexInfo);
}
#if 0
/*
*----------------------------------------------------------------------
*
* CopySuperBlock --
*
* Copy the super block from the first sector of the disk to
* the first sector of the partition being formatted.
*
* Results:
* A return code from the I/O.
*
* Side effects:
* Writes on the zero'th sector of the partition.
*
*----------------------------------------------------------------------
*/
ReturnStatus
CopySuperBlock(firstPartFID, partFID)
int firstPartFID;
int partFID;
{
ReturnStatus status;
char *block;
block = (char *)malloc(DEV_BYTES_PER_SECTOR);
status = Disk_SectorRead(firstPartFID, 0, 1, block);
if (status != SUCCESS) {
return(status);
}
status = Disk_SectorWrite(partFID, 0, 1, block);
return(status);
}
#endif
@
1.13
log
@Preserve creation times on files, and print out error message
if a file can't be read.
@
text
@d38 1
a38 1
static char rcsid[] = "$Header: /sprite/src/admin/fsinstall/RCS/fsmake.c,v 1.12 89/12/13 14:06:45 rab Exp Locker: ouster $ SPRITE (Berkeley)";
d83 1
d106 2
d308 1
a308 1
if (diskInfoPtr == NULL) {
@
1.12
log
@Fixed problem with reading first sector.
@
text
@d38 1
a38 1
static char rcsid[] = "$Header: /sprite/src/admin/fsinstall/RCS/fsmake.c,v 1.11 89/11/29 16:49:52 ouster Exp Locker: rab $ SPRITE (Berkeley)";
d52 1
d126 6
d251 2
d880 1
a880 1
InitDesc(fileDescPtr, FS_FILE, 0, -1, -1, 0, 0, 0700);
d885 1
a885 1
0, 0755);
d1733 1
a1733 1
0, 0, statBuf.st_mode & 07777);
d1756 1
a1756 1
0, 0, statBuf.st_mode & 07777);
d1766 4
d1779 1
a1779 1
0, 0, 0777);
d1840 4
d2057 1
a2057 1
gid, permissions)
d2066 1
a2067 1
Time time;
d2091 2
a2092 2
* Set the time stamps. This assumes that universal time, not local
* time, is used for time stamps.
d2094 1
a2094 2
gettimeofday(&time, NULL);
fileDescPtr->createTime = time.seconds;
d2096 2
a2097 2
fileDescPtr->descModifyTime = time.seconds;
fileDescPtr->dataModifyTime = time.seconds;
d2334 1
a2334 1
devPermissions);
a2387 1
@
1.11
log
@Always create things as root. Also, read permissions from dev_file.
@
text
@d38 1
a38 1
static char rcsid[] = "$Header: fsmake.c,v 1.1 89/11/29 13:43:45 ouster Locked $ SPRITE (Berkeley)";
d51 2
d200 15
d241 2
d259 2
d294 25
a318 3
/*
* Read the copy of the super block at the beginning of the partition
* to find out basic disk geometry and where to write the domain header.
d320 5
a324 14
#ifdef notdef
diskInfoPtr = Disk_ReadDiskInfo(partFID, partition);
#endif
diskInfoPtr = (Disk_Info *)NULL;
if (diskInfoPtr == (Disk_Info *)NULL) {
if (diskType != NULL) {
/*
* See if we can find the information in /etc/disktab.
*/
diskInfoPtr = ScanDiskTab();
}
if (diskInfoPtr == (Disk_Info *)NULL) {
fprintf(stderr,"MakeFilesystem: Unable to read super block.\n");
return(1);
d326 15
a341 1
d349 1
d362 1
d387 2
a388 2
CopyTree(dirName, FSDM_ROOT_FILE_NUMBER, &rootDesc, FSDM_ROOT_FILE_NUMBER,
FALSE, "/");
d398 1
d2096 1
a2096 1
if (numBlocks >= FSDM_NUM_DIRECT_BLOCKS) {
d2336 37
@
1.10
log
@Make sure dev directory is the root dev directory.
@
text
@d38 1
a38 1
static char rcsid[] = "$Header: /sprite/src/admin/fsinstall/RCS/fsmake.c,v 1.9 89/11/27 21:44:16 jhh Exp Locker: rab $ SPRITE (Berkeley)";
d55 1
a55 1
#ifdef sprite
d67 1
a67 1
Boolean printOnly = TRUE; /* Stop after computing the domain header
d75 1
a75 1
int spriteID = 0; /* This machines sprite id. */
d91 1
a91 1
"Test: print results, don't write disk (TRUE)"},
d93 1
a93 1
"Write the disk (FALSE)"},
d820 1
a820 1
InitDesc(fileDescPtr, FS_FILE, 0, -1, -1, 0, 0);
d824 2
a825 1
InitDesc(fileDescPtr, FS_DIRECTORY, FS_BLOCK_SIZE, -1, -1, 0, 0);
d1673 1
a1673 1
statBuf.st_uid, statBuf.st_gid);
d1696 1
a1696 1
statBuf.st_uid, statBuf.st_gid);
d1715 1
a1715 1
statBuf.st_uid, statBuf.st_gid);
d1988 2
a1989 1
InitDesc(fileDescPtr, fileType, numBytes, devType, devUnit, uid, gid)
d1997 1
d2004 1
a2004 1
fileDescPtr->permissions = 0755;
d2244 1
d2260 2
a2261 1
if (sscanf(buf, "%s %d %d", fileName, &devType, &devUnit) != 3) {
d2266 2
a2267 1
InitDesc(&fileFD, FS_DEVICE, 0, devType, devUnit, 0, 0);
d2273 2
a2274 2
printf("Device: %s, %d, %d\n",
fileName, devType, devUnit);
@
1.9
log
@*** empty log message ***
@
text
@d38 1
a38 1
static char rcsid[] = "$Header: /user2/rab/fsinstall/RCS/fsmake.c,v 1.6 89/06/19 13:18:14 mnelson Exp Locker: rab $ SPRITE (Berkeley)";
d1644 2
a1645 1
if (strcmp(fileName, "dev") == 0) {
@
1.8
log
@*** empty log message ***
@
text
@d2042 1
a2042 1
fileDescPtr->numKbytes = numBlocks * (FS_BLOCK_SIZE / 1024);
@
1.7
log
@*** empty log message ***
@
text
@d1149 5
d1297 3
a1299 1
* Write out the disk header.
d1301 2
d1308 2
@
1.6
log
@Now can handle directories larger than 4K.
@
text
@d38 2
a39 2
static char rcsid[] = "$Header: fsmake.c,v 1.5 89/05/19 17:40:11 mnelson Locked $ SPRITE (Berkeley)";
#endif not lint
d55 7
d109 1
a109 1
FsFileDescriptor *fdPtr; /* The file descriptor being
d137 4
a140 4
FsDirEntry *OpenDir();
FsDirEntry *NextDirEntry();
void CloseDir();
FsDirEntry *AddToDirectory();
d178 1
a178 1
FsFileDescriptor devFD; /* The file descriptor for the dev
d180 1
a180 1
FsFileDescriptor *devFDPtr; /* Pointer to the file descriptor for
d186 1
a186 1
FsDomainHeader *domainPtr; /* The domain the we are initializing.*/
d191 1
a191 1
FsSummaryInfo *summaryPtr; /* Summary information for the domain.*/
d294 1
a294 1
domainPtr = (FsDomainHeader *)
d309 1
a309 1
summaryPtr = (FsSummaryInfo *) malloc(DEV_BYTES_PER_SECTOR);
d330 1
a330 1
FsFileDescriptor rootDesc;
d336 2
a337 2
ReadFileDesc(FS_ROOT_FILE_NUMBER, &rootDesc);
CopyTree(dirName, FS_ROOT_FILE_NUMBER, &rootDesc, FS_ROOT_FILE_NUMBER,
d339 1
a339 1
WriteFileDesc(FS_ROOT_FILE_NUMBER, &rootDesc);
d385 1
a385 1
register FsGeometry *geoPtr;
d387 1
a387 1
domainPtr->magic = FS_DOMAIN_MAGIC;
d433 1
a433 1
register FsGeometry *geoPtr; /* Fancy geometry information */
d566 1
a566 1
for (index = numBlocks; index < FS_MAX_ROT_POSITIONS; index++){
d591 1
a591 1
for (index = 0 ; index < FS_MAX_ROT_POSITIONS ; index++) {
d620 1
a620 1
register FsGeometry *geoPtr;
d656 1
a656 1
numFiles &= ~(FS_FILE_DESC_PER_BLOCK-1);
d667 2
a668 2
numBlocks -= numFiles / FS_FILE_DESC_PER_BLOCK;
offset += numFiles / FS_FILE_DESC_PER_BLOCK;
d696 1
a696 1
numFiles -= numBlocksNeeded * FS_FILE_DESC_PER_BLOCK;
d707 1
a707 1
numFiles += extraBlocks * FS_FILE_DESC_PER_BLOCK;
d790 1
a790 1
register FsFileDescriptor *fileDescPtr;
d812 1
a812 1
index < FS_FILE_DESC_PER_BLOCK;
d814 6
a819 6
fileDescPtr = (FsFileDescriptor *)((int)block +
index * FS_MAX_FILE_DESC_SIZE);
fileDescPtr->magic = FS_FD_MAGIC;
if (index < FS_BAD_BLOCK_FILE_NUMBER) {
fileDescPtr->flags = FS_FD_RESERVED;
} else if (index == FS_BAD_BLOCK_FILE_NUMBER) {
d823 1
a823 1
} else if (index == FS_ROOT_FILE_NUMBER) {
d830 1
a830 1
fileDescPtr->flags = FS_FD_FREE;
d850 1
a850 1
index < FS_FILE_DESC_PER_BLOCK;
d852 4
a855 4
fileDescPtr = (FsFileDescriptor *)((int)block + index *
FS_MAX_FILE_DESC_SIZE);
fileDescPtr->magic = FS_FD_MAGIC;
fileDescPtr->flags = FS_FD_FREE;
d860 1
a860 1
for (index = FS_FILE_DESC_PER_BLOCK;
d862 1
a862 1
index += FS_FILE_DESC_PER_BLOCK) {
d864 1
a864 1
domainPtr->fileDescOffset + (index/FS_FILE_DESC_PER_BLOCK),
d907 1
a907 1
* File number 2 (FS_ROOT_FILE_NUMBER) is the root directory of the domain.
d1050 1
a1050 1
FsDirEntry *dirEntryPtr;
d1055 1
a1055 1
CreateDir(block, FS_ROOT_FILE_NUMBER, FS_ROOT_FILE_NUMBER);
d1060 1
a1060 1
dirEntryPtr = (FsDirEntry *)block;
d1063 1
a1063 1
dirEntryPtr = (FsDirEntry *)((int)block + offset);
d1122 1
a1122 1
FsDiskPartition partTable[FS_NUM_DISK_PARTS];
d1172 1
a1172 1
for (i = 0; i < FS_NUM_DISK_PARTS; i++) {
d1206 1
a1206 1
for (i = 0; i < FS_NUM_DISK_PARTS; i++) {
d1236 1
a1236 1
for (i = 0; i < FS_NUM_DISK_PARTS; i++) {
d1248 1
a1248 1
FsDiskHeader header;
d1254 1
a1254 1
header.magic = FS_DISK_MAGIC;
d1263 1
a1263 1
header.numDomainSectors = FS_NUM_DOMAIN_SECTORS;
d1269 1
a1269 1
header.checkSum = FS_DISK_MAGIC;
d1286 1
a1286 1
if (checkSum != FS_DISK_MAGIC) {
d1311 1
a1311 1
diskInfoPtr->numDomainSectors = FS_NUM_DOMAIN_SECTORS;
d1456 1
a1456 1
FsFileDescriptor *fdPtr;
d1462 2
a1463 2
blockNum = domainPtr->fileDescOffset + fdNum / FS_FILE_DESC_PER_BLOCK;
offset = (fdNum & (FS_FILE_DESC_PER_BLOCK - 1)) * FS_MAX_FILE_DESC_SIZE;
d1469 1
a1469 1
bcopy((Address)&block[offset], (Address)fdPtr, sizeof(FsFileDescriptor));
d1491 1
a1491 1
FsFileDescriptor *fdPtr;
d1497 2
a1498 2
blockNum = domainPtr->fileDescOffset + fdNum / FS_FILE_DESC_PER_BLOCK;
offset = (fdNum & (FS_FILE_DESC_PER_BLOCK - 1)) * FS_MAX_FILE_DESC_SIZE;
d1504 1
a1504 1
bcopy(fdPtr, (Address)&block[offset], sizeof(FsFileDescriptor));
d1538 1
a1538 1
FsFileDescriptor *dirFDPtr; /* File descriptor of directory. */
d1544 1
a1544 1
FsDirEntry *unixDirEntPtr;
d1546 1
a1546 1
FsDirEntry *spriteDirEntPtr;
d1549 2
a1550 2
FsFileDescriptor newFD;
FsFileDescriptor *newFDPtr;
d1559 1
a1559 1
getcwd(pathName, 1024);
d1578 1
a1578 1
if (spriteDirEntPtr == (FsDirEntry *)NULL) {
d1599 1
a1599 1
for (unixDirEntPtr = (FsDirEntry *)readdir(unixDirPtr);
d1601 1
a1601 1
unixDirEntPtr = (FsDirEntry *)readdir(unixDirPtr)) {
d1709 1
a1709 1
if (blockNum == FS_NUM_DIRECT_BLOCKS) {
d1724 1
a1724 1
*intPtr = FS_NIL_INDEX;
d1727 2
a1728 2
if (blockNum >= FS_NUM_DIRECT_BLOCKS) {
indIndexPtr[blockNum - FS_NUM_DIRECT_BLOCKS] =
d1764 1
a1764 1
if (newFDPtr->indirect[0] != FS_NIL_INDEX) {
d1779 1
a1779 1
if (spriteDirEntPtr == (FsDirEntry *)NULL) {
d1791 2
d1812 1
a1812 1
static FsDirEntry *
d1814 1
a1814 1
FsFileDescriptor *fdPtr; /* The file descriptor for the
d1824 2
a1825 2
return((FsDirEntry *) NULL);
} else if ((fdPtr->lastByte + 1) % FS_DIR_BLOCK_SIZE != 0) {
d1830 1
a1830 1
return((FsDirEntry *)NULL);
d1855 1
a1855 1
return((FsDirEntry *) indexInfoPtr->dirBlock);
d1875 1
a1875 1
FsDirEntry *
d1878 1
a1878 1
FsDirEntry *dirEntryPtr;
d1885 1
a1885 1
return((FsDirEntry *)
d1888 1
a1888 1
FsFileDescriptor *fdPtr;
d1914 3
a1916 3
for (i = 0, dirEntryPtr = (FsDirEntry *)indexInfoPtr->dirBlock;
i < FS_BLOCK_SIZE / FS_DIR_BLOCK_SIZE;
i++,dirEntryPtr=(FsDirEntry *)((unsigned)dirEntryPtr+FS_DIR_BLOCK_SIZE)) {
d1918 1
a1918 1
dirEntryPtr->recordLength = FS_DIR_BLOCK_SIZE;
d1922 1
a1922 1
return((FsDirEntry *) indexInfoPtr->dirBlock);
d1976 1
a1976 1
FsFileDescriptor *fileDescPtr;
d1987 1
a1987 1
fileDescPtr->flags = FS_FD_ALLOC;
d2020 2
a2021 2
for (index = 0; index < FS_NUM_DIRECT_BLOCKS ; index++) {
fileDescPtr->direct[index] = FS_NIL_INDEX;
d2023 2
a2024 2
for (index = 0; index < FS_NUM_INDIRECT_BLOCKS ; index++) {
fileDescPtr->indirect[index] = FS_NIL_INDEX;
d2030 1
a2030 1
if (numBlocks >= FS_NUM_DIRECT_BLOCKS) {
d2062 1
a2062 1
FsDomainHeader *domainPtr;
d2100 1
a2100 1
FsDirEntry *dirEntryPtr;
d2106 1
a2106 1
dirEntryPtr = (FsDirEntry *)block;
d2110 1
a2110 1
dirEntryPtr->recordLength = FsDirRecLength(length);
d2115 1
a2115 1
dirEntryPtr = (FsDirEntry *)((int)block + offset);
d2119 1
a2119 1
dirEntryPtr->recordLength = FS_DIR_BLOCK_SIZE - offset;
d2125 3
a2127 3
for (dirEntryPtr = (FsDirEntry *)&block[FS_DIR_BLOCK_SIZE], i = 1;
i < FS_BLOCK_SIZE / FS_DIR_BLOCK_SIZE;
i++,dirEntryPtr=(FsDirEntry *)((int)dirEntryPtr + FS_DIR_BLOCK_SIZE)) {
d2129 1
a2129 1
dirEntryPtr->recordLength = FS_DIR_BLOCK_SIZE;
d2150 1
a2150 1
FsDirEntry *
d2153 1
a2153 1
FsDirEntry *dirEntryPtr;
d2163 1
a2163 1
recordLength = FsDirRecLength(nameLength);
d2165 1
a2165 1
while (dirEntryPtr != (FsDirEntry *) NULL) {
d2167 1
a2167 1
oldRecLength = FsDirRecLength(dirEntryPtr->nameLength);
d2172 1
a2172 1
(FsDirEntry *) ((int) dirEntryPtr + oldRecLength);
d2188 1
a2188 1
if (leftOver > FS_DIR_ENTRY_HEADER) {
d2190 1
a2190 1
dirEntryPtr =(FsDirEntry *) ((int) dirEntryPtr + recordLength);
d2224 1
a2224 1
FsDirEntry *dirEntryPtr;
d2230 1
a2230 1
FsFileDescriptor fileFD;
d2239 1
a2239 1
if (dirEntryPtr == (FsDirEntry *)NULL) {
d2255 1
a2255 1
printf("Device: /dev/%s, %d, %d\n",
d2260 1
a2260 1
if (dirEntryPtr == (FsDirEntry *)NULL) {
@
1.5
log
@Fixed bug in adding devices and setting the bitmap.
@
text
@d38 1
a38 1
static char rcsid[] = "$Header: fsmake.c,v 1.4 89/05/19 16:56:39 mnelson Locked $ SPRITE (Berkeley)";
a66 1
char *firstPartName = defaultFirstPartName;
a86 2
{OPT_STRING, "initialPart", (Address)&firstPartName,
"Name of initial partition (\"a\")"},
d215 1
a215 1
char firstPartitionName[64];
d251 1
a251 1
sprintf(firstPartitionName, "/dev/%s%s", deviceName, firstPartName);
d254 1
a254 1
partFID = open(firstPartitionName, O_RDONLY);
d256 1
a256 1
partFID = open(firstPartitionName, O_RDWR);
d270 1
d272 2
d1544 3
d1548 6
d1572 2
a1573 2
if (chdir("..") < 0) {
perror("..");
d1577 11
a1594 1
struct stat statBuf;
d1606 10
a1615 3
if (lstat(fileName, &statBuf) < 0) {
perror(fileName);
exit(1);
a1643 1
d1663 1
a1663 1
printf("Creating directory: %s\n", newPath);
d1674 1
a1674 1
printf("Creating file: %s%s\n", path, fileName);
d1696 1
a1696 1
printf("Creating symbolic link: %s%s -> %s\n",
d1780 2
a1781 2
if (chdir("..") < 0) {
perror(".. (2)");
a1818 3
} else if (indexInfoPtr->blockAddr == FS_NIL_INDEX) {
fprintf(stderr, "OpenDir: NIL block pointer\n");
exit(1);
d1872 1
a1872 1
if (indexInfoPtr->dirOffset == indexInfoPtr->fdPtr->lastByte + 1) {
d1874 1
a1874 2
* We reached the end of the directory. Write out the directory
* block if necessary.
d1876 11
d1889 1
a1889 1
1, indexInfoPtr->dirBlock) < 0) {
d1891 1
a1891 1
indexInfoPtr->blockAddr);
d1895 19
a1913 1
return((FsDirEntry *)NIL);
a1914 11
if (indexInfoPtr->dirOffset < FS_BLOCK_SIZE) {
/*
* The next directory entry is in the current block.
*/
return((FsDirEntry *)
&(indexInfoPtr->dirBlock[indexInfoPtr->dirOffset]));
} else {
fprintf(stderr, "NextDirEntry: We are in the second block?\n");
exit(1);
}
d2246 1
a2246 1
printf("Creating device: /dev/%s, %d, %d\n",
@
1.4
log
@*** empty log message ***
@
text
@d38 1
a38 1
static char rcsid[] = "$Header: fsmake.c,v 1.3 89/05/15 19:39:56 mnelson Locked $ SPRITE (Berkeley)";
d1994 1
a1994 1
int fragMasks[FS_FRAGMENTS_PER_BLOCK] = {0x08, 0x0c, 0x0e, 0x0f};
d2212 1
a2212 1
if (dirEntryPtr = (FsDirEntry *)NULL) {
@
1.3
log
@*** empty log message ***
@
text
@d38 1
a38 1
static char rcsid[] = "$Header: fsmake.c,v 1.2 89/05/03 19:00:24 mnelson Exp $ SPRITE (Berkeley)";
d813 1
a813 1
InitDesc(fileDescPtr, FS_FILE, 0, -1, -1);
d817 1
a817 1
InitDesc(fileDescPtr, FS_DIRECTORY, FS_BLOCK_SIZE, -1, -1);
d1587 1
a1587 1
if (stat(fileName, &statBuf) < 0) {
d1627 2
a1628 1
InitDesc(newFDPtr, FS_DIRECTORY, FS_BLOCK_SIZE, -1, -1);
d1640 2
a1641 1
} else if (statBuf.st_mode & S_GFREG) {
d1647 28
a1674 1
printf("Creating file: %s%s\n", path, fileName);
a1675 12
/*
* Copy the file over.
*/
InitDesc(newFDPtr, FS_FILE, statBuf.st_size, -1, -1);
fd = open(fileName, 0);
if (fd < 0) {
perror(fileName);
exit(1);
}
blockNum = 0;
toRead = statBuf.st_size;
len = read(fd, fileBlock, FS_BLOCK_SIZE);
d1726 3
d1927 1
a1927 1
InitDesc(fileDescPtr, fileType, numBytes, devType, devUnit)
d1933 2
d1942 2
a1943 2
fileDescPtr->uid = 0;
fileDescPtr->gid = 0;
d2201 1
a2201 1
InitDesc(&fileFD, FS_DEVICE, 0, devType, devUnit);
@
1.2
log
@*** empty log message ***
@
text
@d38 1
a38 1
static char rcsid[] = "$Header: fsmake.c,v 1.1 89/05/02 10:50:04 mnelson Locked $ SPRITE (Berkeley)";
d1679 2
a1680 1
indIndexPtr[blockNum - FS_NUM_DIRECT_BLOCKS] = freeBlockNum;
d1934 2
a1935 2
fileDescPtr->devType = -1;
fileDescPtr->devUnit = -1;
d2182 3
@
1.1
log
@Initial revision
@
text
@d6 29
a34 2
* Copyright (C) 1986 Regents of the University of California
* All rights reserved.
d38 1
a38 1
static char rcsid[] = "$Header: /sprite/src/admin/fsmake/RCS/fsmake.c,v 1.6 89/03/03 17:08:18 jhh Exp $ SPRITE (Berkeley)";
d48 6
a61 2
Boolean makeFile = FALSE; /* Make a file in the root directory,
* this is used when testing the filesystem */
a63 7
/*
* The following are used to go from a command line like
* makeFilesystem -D rsd0 -P b
* to /dev/rsd0a - for the partition that has the disk label
* and to /dev/rsd0b - for the partition to format.
*/
d68 6
a73 4
char defaultDevDirectory[] = "/dev/";
char *devDirectory = defaultDevDirectory;
char *diskType = NULL;
int spriteID = 0;
a79 2
{OPT_TRUE, "file", (Address)&makeFile,
"Make a file in the root directory (FALSE)"},
a87 2
{OPT_STRING, "dir", (Address)&devDirectory,
"Name of device directory (\"/dev/\")"},
d94 4
d102 17
d125 6
a130 7
void SetRootFileDescriptor();
void SetBadBlockFileDescriptor();
void SetLostFoundFileDescriptor();
void SetEmptyFileDescriptor();
ReturnStatus WriteFileDesc();
ReturnStatus WriteFileDescBitmap();
ReturnStatus WriteBitmap();
d133 12
d146 48
a218 1
int firstPartFID;
d232 1
a232 1
fprintf(stderr, "No sprite ID\n");
d254 1
a254 3
(void) strcpy(firstPartitionName, devDirectory); /* eg. /dev/ */
(void) strcat(firstPartitionName, deviceName); /* eg. /dev/rxy0 */
(void) strcat(firstPartitionName, firstPartName); /* eg. /dev/rxy0a */
d257 1
a257 1
firstPartFID = open(firstPartitionName, O_RDONLY);
d259 1
a259 1
firstPartFID = open(firstPartitionName, O_RDWR);
d261 1
a261 1
if (firstPartFID < 0 ) {
a266 1
status = MakeFilesystem(firstPartFID, partName[0] - 'a', spriteID);
d268 1
a268 33
fflush(stderr);
fflush(stdout);
(void)close(firstPartFID);
exit(status);
}
/*
*----------------------------------------------------------------------
*
* MakeFilesystem --
*
* Format a disk partition, or domain, to be an empty filesystem.
*
* Results:
* An error code.
*
* Side effects:
* Write all over the disk partition.
*
*----------------------------------------------------------------------
*/
int
MakeFilesystem(firstPartFID, partition, spriteID)
int firstPartFID; /* Handle on the first partition of the disk */
int partition; /* Index of parition that is to be formatted */
int spriteID; /* Host ID of the machine with the disks, this
* gets written on the disk and used at boot time */
{
int status;
Disk_Info *diskInfoPtr;
FsDomainHeader *headerPtr;
FsSummaryInfo *summaryPtr;
d273 1
a273 1
diskInfoPtr = Disk_ReadDiskInfo(firstPartFID, partition);
d279 1
a279 1
diskInfoPtr = ScanDiskTab(firstPartFID, partition, diskType);
d287 1
a287 1
headerPtr = (FsDomainHeader *)
d289 3
a291 2
SetDomainHeader(diskInfoPtr, headerPtr, spriteID, partition);
Disk_PrintDomainHeader(headerPtr);
d294 2
a295 2
status = Disk_SectorWrite(firstPartFID, diskInfoPtr->domainSector,
diskInfoPtr->numDomainSectors, (Address)headerPtr);
d301 1
d303 1
a303 1
SetSummaryInfo(diskInfoPtr, headerPtr, summaryPtr);
d306 1
a306 1
status = Disk_SectorWrite(firstPartFID, diskInfoPtr->summarySector, 1,
d314 42
a355 5
WriteFileDesc(headerPtr, firstPartFID);
WriteBitmap(headerPtr, firstPartFID);
WriteRootDirectory(headerPtr, firstPartFID);
WriteLostFoundDirectory(headerPtr, firstPartFID);
return(0);
d376 1
a376 6
SetDomainHeader(diskInfoPtr, headerPtr, spriteID, partition)
Disk_Info *diskInfoPtr; /* Information from the super block */
FsDomainHeader *headerPtr; /* Reference to domain header to fill
* in */
int spriteID; /* Host ID of machine with the disks */
int partition; /* Index of partition to format */
d380 3
a382 3
headerPtr->magic = FS_DOMAIN_MAGIC;
headerPtr->firstCylinder = diskInfoPtr->firstCylinder;
headerPtr->numCylinders = diskInfoPtr->numCylinders;
d392 4
a395 4
headerPtr->device.serverID = spriteID;
headerPtr->device.type = -1;
headerPtr->device.unit = partition;
headerPtr->device.data = (ClientData)-1;
d397 2
a398 2
geoPtr = &headerPtr->geometry;
SetDiskGeometry(diskInfoPtr, geoPtr);
d400 1
a400 1
SetDomainParts(diskInfoPtr, headerPtr);
d425 1
a425 2
SetDiskGeometry(diskInfoPtr, geoPtr)
register Disk_Info *diskInfoPtr; /* Basic geometry information */
d611 1
a611 3
SetDomainParts(diskInfoPtr, headerPtr)
register Disk_Info *diskInfoPtr;
register FsDomainHeader *headerPtr;
d626 1
a626 1
geoPtr = &headerPtr->geometry;
d652 1
a652 1
headerPtr->fdBitmapOffset = offset;
d654 3
a656 3
headerPtr->fdBitmapBlocks = (bitmapBytes - 1) / FS_BLOCK_SIZE + 1;
numBlocks -= headerPtr->fdBitmapBlocks;
offset += headerPtr->fdBitmapBlocks;
d658 2
a659 2
headerPtr->fileDescOffset = offset;
headerPtr->numFileDesc = numFiles;
d666 2
a667 2
headerPtr->bitmapOffset = offset;
headerPtr->dataOffset = ((offset-1) / geoPtr->blocksPerCylinder + 1)
d669 1
a669 1
headerPtr->dataBlocks = headerPtr->numCylinders *
d671 2
a672 2
headerPtr->dataOffset;
bitmapBytes = (headerPtr->dataBlocks * DISK_KBYTES_PER_BLOCK -
d674 1
a674 1
headerPtr->bitmapBlocks = (bitmapBytes - 1) / FS_BLOCK_SIZE + 1;
d680 2
a681 2
if (headerPtr->dataOffset - headerPtr->bitmapOffset <
headerPtr->bitmapBlocks) {
d687 2
a688 2
numBlocksNeeded = headerPtr->bitmapBlocks -
(headerPtr->dataOffset - headerPtr->bitmapOffset);
d690 2
a691 2
} else if (headerPtr->dataOffset - headerPtr->bitmapOffset >
headerPtr->bitmapBlocks) {
d698 2
a699 2
extraBlocks = headerPtr->dataOffset - headerPtr->bitmapOffset -
headerPtr->bitmapBlocks;
d702 3
a704 3
} while (headerPtr->dataOffset - headerPtr->bitmapOffset !=
headerPtr->bitmapBlocks);
headerPtr->dataCylinders = headerPtr->dataBlocks /
d725 1
a725 5
SetSummaryInfo(diskInfoPtr, headerPtr, summaryPtr)
Disk_Info *diskInfoPtr; /* Information from the super block */
FsDomainHeader *headerPtr; /* Domain header to summarize */
FsSummaryInfo *summaryPtr; /* Reference to summary info to
* fill in */
d732 1
a732 2
* 12 blocks are already allocated, 4 for the root directory,
* and 8 more for lost+found.
d734 2
a735 2
summaryPtr->numFreeKbytes = headerPtr->dataBlocks * (FS_BLOCK_SIZE / 1024)
- 12;
d737 2
a738 2
* 4 file descriptors are already used, 0 and 1 are reserved,
* 2 is for the root, and 3 is for lost+found.
d740 1
a740 4
summaryPtr->numFreeFileDesc = headerPtr->numFileDesc - 4;
if (makeFile) {
summaryPtr->numFreeFileDesc--;
}
d765 1
a765 1
* WriteFileDesc --
d777 2
a778 4
ReturnStatus
WriteFileDesc(headerPtr, firstPartFID)
register FsDomainHeader *headerPtr;
int firstPartFID;
d780 1
a780 1
ReturnStatus status;
d786 1
a786 1
bitmap = MakeFileDescBitmap(headerPtr);
d788 3
a790 3
status = Disk_BlockWrite(firstPartFID, headerPtr,
headerPtr->fdBitmapOffset,
headerPtr->fdBitmapBlocks, (Address)bitmap);
d792 2
a793 1
return(status);
d813 3
a815 1
SetBadBlockFileDescriptor(fileDescPtr);
d817 5
a821 5
SetRootFileDescriptor(fileDescPtr);
} else if (index == FS_LOST_FOUND_FILE_NUMBER) {
SetLostFoundFileDescriptor(fileDescPtr);
} else if ((index == FS_LOST_FOUND_FILE_NUMBER+1) && makeFile) {
SetEmptyFileDescriptor(fileDescPtr);
d831 2
a832 2
status = Disk_BlockWrite(firstPartFID, headerPtr,
headerPtr->fileDescOffset,
d835 2
a836 1
return(status);
d854 1
a854 1
index < headerPtr->numFileDesc;
d856 2
a857 2
status = Disk_BlockWrite(firstPartFID, headerPtr,
headerPtr->fileDescOffset + (index/FS_FILE_DESC_PER_BLOCK),
d860 3
a862 1
return(status);
a864 2
} else {
status = 0;
a865 1
return(status);
a866 22
/*
*----------------------------------------------------------------------
*
* SetRootFileDescriptor --
*
* Set up the file descriptor for the root directory.
*
* Results:
* Fill in the file descriptor.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
void
SetRootFileDescriptor(fileDescPtr)
register FsFileDescriptor *fileDescPtr;
{
Time time;
int index;
a867 39
fileDescPtr->flags = FS_FD_ALLOC;
fileDescPtr->fileType = FS_DIRECTORY;
fileDescPtr->permissions = 0755;
fileDescPtr->uid = 0;
fileDescPtr->gid = 0;
fileDescPtr->lastByte = FS_BLOCK_SIZE-1;
fileDescPtr->firstByte = -1;
fileDescPtr->numLinks = 3;
/*
* Can't know device information because that depends on
* the way the system is configured.
*/
fileDescPtr->devServerID = -1;
fileDescPtr->devType = -1;
fileDescPtr->devUnit = -1;
/*
* Set the time stamps. This assumes that universal time, not local
* time, is used for time stamps.
*/
gettimeofday(&time, NULL);
fileDescPtr->createTime = time.seconds;
fileDescPtr->accessTime = 0;
fileDescPtr->descModifyTime = time.seconds;
fileDescPtr->dataModifyTime = time.seconds;
/*
* Place the data in the first filesystem block.
*/
fileDescPtr->direct[0] = 0;
for (index = 1; index < FS_NUM_DIRECT_BLOCKS ; index++) {
fileDescPtr->direct[index] = FS_NIL_INDEX;
}
for (index = 0; index < FS_NUM_INDIRECT_BLOCKS ; index++) {
fileDescPtr->indirect[index] = FS_NIL_INDEX;
}
fileDescPtr->numKbytes = 4;
fileDescPtr->version = 1;
}
a871 180
* SetBadBlockFileDescriptor --
*
* Set up the file descriptor for the bad block file.
*
* Results:
* Fill in the file descriptor.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
void
SetBadBlockFileDescriptor(fileDescPtr)
register FsFileDescriptor *fileDescPtr;
{
Time time;
int index;
fileDescPtr->flags = FS_FD_ALLOC;
fileDescPtr->fileType = FS_FILE;
fileDescPtr->permissions = 0000;
fileDescPtr->uid = 0;
fileDescPtr->gid = 0;
fileDescPtr->lastByte = -1;
fileDescPtr->firstByte = -1;
fileDescPtr->numLinks = 0; /* Intentionally unreferenced */
/*
* Can't know device information because that depends on
* the way the system is configured.
*/
fileDescPtr->devServerID = -1;
fileDescPtr->devType = -1;
fileDescPtr->devUnit = -1;
/*
* Set the time stamps. This assumes that universal time, not local
* time, is used for time stamps.
*/
gettimeofday(&time, NULL);
fileDescPtr->createTime = time.seconds;
fileDescPtr->accessTime = 0;
fileDescPtr->descModifyTime = time.seconds;
fileDescPtr->dataModifyTime = time.seconds;
/*
* Place the data in the first filesystem block.
*/
for (index = 0; index < FS_NUM_DIRECT_BLOCKS ; index++) {
fileDescPtr->direct[index] = FS_NIL_INDEX;
}
for (index = 0; index < FS_NUM_INDIRECT_BLOCKS ; index++) {
fileDescPtr->indirect[index] = FS_NIL_INDEX;
}
fileDescPtr->numKbytes = 0;
fileDescPtr->version = 1;
}
/*
*----------------------------------------------------------------------
*
* SetLostFoundFileDescriptor --
*
* Set up the file descriptor for the lost and found directory.
*
* Results:
* Fill in the file descriptor.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
void
SetLostFoundFileDescriptor(fileDescPtr)
register FsFileDescriptor *fileDescPtr;
{
Time time;
int index;
fileDescPtr->flags = FS_FD_ALLOC;
fileDescPtr->fileType = FS_DIRECTORY;
fileDescPtr->permissions = 0755;
fileDescPtr->uid = 0;
fileDescPtr->gid = 0;
fileDescPtr->lastByte = FS_NUM_LOST_FOUND_BLOCKS * FS_BLOCK_SIZE - 1;
fileDescPtr->firstByte = -1;
fileDescPtr->numLinks = 2;
/*
* Can't know device information because that depends on
* the way the system is configured.
*/
fileDescPtr->devServerID = -1;
fileDescPtr->devType = -1;
fileDescPtr->devUnit = -1;
/*
* Set the time stamps. This assumes that universal time, not local
* time, is used for time stamps.
*/
gettimeofday(&time, NULL);
fileDescPtr->createTime = time.seconds;
fileDescPtr->accessTime = 0;
fileDescPtr->descModifyTime = time.seconds;
fileDescPtr->dataModifyTime = time.seconds;
for (index = 0; index < FS_NUM_LOST_FOUND_BLOCKS ; index++) {
fileDescPtr->direct[index] = FS_FRAGMENTS_PER_BLOCK * (index + 1);
}
for (; index < FS_NUM_DIRECT_BLOCKS ; index++) {
fileDescPtr->direct[index] = FS_NIL_INDEX;
}
for (index = 0; index < FS_NUM_INDIRECT_BLOCKS ; index++) {
fileDescPtr->indirect[index] = FS_NIL_INDEX;
}
fileDescPtr->numKbytes = 8;
fileDescPtr->version = 1;
}
/*
*----------------------------------------------------------------------
*
* SetEmptyFileDescriptor --
*
* Set up a file descriptor for an empty file.
*
* Results:
* Fill in the file descriptor.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
void
SetEmptyFileDescriptor(fileDescPtr)
register FsFileDescriptor *fileDescPtr;
{
Time time;
int index;
fileDescPtr->flags = FS_FD_ALLOC;
fileDescPtr->fileType = FS_FILE;
fileDescPtr->permissions = 0666;
fileDescPtr->uid = 0;
fileDescPtr->gid = 0;
fileDescPtr->lastByte = -1;
fileDescPtr->firstByte = -1;
fileDescPtr->numLinks = 1;
/*
* Can't know device information because that depends on
* the way the system is configured.
*/
fileDescPtr->devServerID = -1;
fileDescPtr->devType = -1;
fileDescPtr->devUnit = -1;
/*
* Set the time stamps. This assumes that universal time, not local
* time, is used for time stamps.
*/
gettimeofday(&time, NULL);
fileDescPtr->createTime = time.seconds;
fileDescPtr->accessTime = 0;
fileDescPtr->descModifyTime = time.seconds;
fileDescPtr->dataModifyTime = time.seconds;
for (index = 0; index < FS_NUM_DIRECT_BLOCKS ; index++) {
fileDescPtr->direct[index] = FS_NIL_INDEX;
}
for (index = 0; index < FS_NUM_INDIRECT_BLOCKS ; index++) {
fileDescPtr->indirect[index] = FS_NIL_INDEX;
}
fileDescPtr->numKbytes = 0;
fileDescPtr->version = 1;
}
/*
*----------------------------------------------------------------------
*
d885 1
a885 2
MakeFileDescBitmap(headerPtr)
register FsDomainHeader *headerPtr;
d893 1
a893 1
bitmap = (char *)malloc((unsigned) headerPtr->fdBitmapBlocks *
d895 1
a895 1
bzero((Address)bitmap, headerPtr->fdBitmapBlocks * FS_BLOCK_SIZE);
d898 1
a898 1
* Reserve file descriptors 0, 1, 2, and 3. File number 0 is not used at
a900 2
* File number 3 (FS_LOST_FOUND_NUMBER) is the directory where lost
* files are stored.
d904 1
a904 1
bitmap[0] |= 0xf0;
a906 6
* Reserve file descriptor # 4 for an empty file.
*/
if (makeFile) {
bitmap[0] |= 0x08;
}
/*
d910 2
a911 2
index = headerPtr->numFileDesc / BITS_PER_BYTE;
if (headerPtr->numFileDesc % BITS_PER_BYTE) {
d916 1
a916 1
for (bitIndex = headerPtr->numFileDesc % BITS_PER_BYTE;
d923 1
a923 1
for ( ; index < headerPtr->fdBitmapBlocks * FS_BLOCK_SIZE; index++) {
d928 1
a928 1
Disk_PrintFileDescBitmap(headerPtr, bitmap);
d936 1
a936 1
* WriteBitmap --
d939 1
a939 2
* first 1K fragment is allocated to the root directory and 8K is
* allocated to lost and found.
d949 2
a950 4
ReturnStatus
WriteBitmap(headerPtr, firstPartFID)
register FsDomainHeader *headerPtr;
int firstPartFID;
d958 2
a959 2
bitmap = (char *)malloc((unsigned) headerPtr->bitmapBlocks * FS_BLOCK_SIZE);
bzero(bitmap, headerPtr->bitmapBlocks * FS_BLOCK_SIZE);
d961 1
a961 2
* Set the bit corresponding to the 4K used for the root directory
* and the next 8K reserved for lost and found.
d967 1
a967 2
bitmap[0] |= 0xff;
bitmap[1] |= 0xf0;
d973 1
a973 1
kbytesPerCyl = headerPtr->geometry.blocksPerCylinder * DISK_KBYTES_PER_BLOCK;
d993 1
a993 1
index < headerPtr->dataBlocks * DISK_KBYTES_PER_BLOCK / BITS_PER_BYTE;
d1004 2
a1005 2
for (index = headerPtr->dataCylinders * bitmapBytesPerCyl;
index < headerPtr->bitmapBlocks * FS_BLOCK_SIZE;
d1010 1
a1010 2
Disk_PrintDataBlockBitmap(headerPtr, bitmap);
status = 0;
d1012 7
a1018 3
status = Disk_BlockWrite(firstPartFID, headerPtr,
headerPtr->bitmapOffset,
headerPtr->bitmapBlocks, (Address)bitmap);
a1019 1
return(status);
d1021 1
d1038 2
a1039 4
ReturnStatus
WriteRootDirectory(headerPtr, firstPartFID)
FsDomainHeader *headerPtr;
int firstPartFID;
a1043 2
char *fileName;
int length;
d1048 1
a1048 1
dirEntryPtr = (FsDirEntry *)block;
a1049 53
fileName = ".";
length = strlen(fileName);
dirEntryPtr->fileNumber = FS_ROOT_FILE_NUMBER;
dirEntryPtr->recordLength = FsDirRecLength(length);
dirEntryPtr->nameLength = length;
strcpy(dirEntryPtr->fileName, fileName);
offset = dirEntryPtr->recordLength;
dirEntryPtr = (FsDirEntry *)((int)block + offset);
fileName = "..";
length = strlen(fileName);
dirEntryPtr->fileNumber = FS_ROOT_FILE_NUMBER;
dirEntryPtr->recordLength = FsDirRecLength(length);
dirEntryPtr->nameLength = length;
strcpy(dirEntryPtr->fileName, fileName);
offset += dirEntryPtr->recordLength;
/*
* Add lost and found.
*/
dirEntryPtr = (FsDirEntry *) ((int)block + offset);
fileName = "lost+found";
length = strlen(fileName);
dirEntryPtr->fileNumber = FS_LOST_FOUND_FILE_NUMBER;
dirEntryPtr->nameLength = length;
strcpy(dirEntryPtr->fileName, fileName);
if (!makeFile) {
dirEntryPtr->recordLength = FS_DIR_BLOCK_SIZE - offset;
} else {
dirEntryPtr->recordLength = FsDirRecLength(length);
offset += dirEntryPtr->recordLength;
dirEntryPtr = (FsDirEntry *)((int)block + offset);
fileName = "testFile";
length = strlen(fileName);
dirEntryPtr->fileNumber = FS_LOST_FOUND_FILE_NUMBER + 1;
dirEntryPtr->nameLength = length;
strcpy(dirEntryPtr->fileName, fileName);
dirEntryPtr->recordLength = FS_DIR_BLOCK_SIZE - offset;
}
/*
* Fill out the rest of the directory with empty blocks.
*/
for (dirEntryPtr = (FsDirEntry *)&block[FS_DIR_BLOCK_SIZE], i = 1;
i < FS_BLOCK_SIZE / FS_DIR_BLOCK_SIZE;
i++,dirEntryPtr=(FsDirEntry *)((int)dirEntryPtr + FS_DIR_BLOCK_SIZE)) {
dirEntryPtr->fileNumber = 0;
dirEntryPtr->recordLength = FS_DIR_BLOCK_SIZE;
dirEntryPtr->nameLength = 0;
}
a1057 9
offset += dirEntryPtr->recordLength;
dirEntryPtr = (FsDirEntry *)((int)block + offset);
Disk_PrintDirEntry(dirEntryPtr);
if (makeFile) {
offset += dirEntryPtr->recordLength;
dirEntryPtr = (FsDirEntry *)((int)block + offset);
Disk_PrintDirEntry(dirEntryPtr);
}
status = 0;
d1064 6
a1069 2
status = Disk_BlockWrite(firstPartFID, headerPtr,
headerPtr->dataOffset, 1, block);
a1070 1
return(status);
d1072 1
a1072 1
d1074 1
a1074 13
*----------------------------------------------------------------------
*
* WriteLostFoundDirectory --
*
* Write the data blocks of the lost and found directory.
*
* Results:
* A return code from the writes.
*
* Side effects:
* Write the root directory"s data block.
*
*----------------------------------------------------------------------
a1075 60
ReturnStatus
WriteLostFoundDirectory(headerPtr, firstPartFID)
register FsDomainHeader *headerPtr;
int firstPartFID;
{
int status;
char *block;
FsDirEntry *dirEntryPtr;
char *fileName;
int length;
int offset;
int i;
block = (char *)malloc(FS_NUM_LOST_FOUND_BLOCKS * FS_BLOCK_SIZE);
dirEntryPtr = (FsDirEntry *)block;
fileName = ".";
length = strlen(fileName);
dirEntryPtr->fileNumber = FS_LOST_FOUND_FILE_NUMBER;
dirEntryPtr->recordLength = FsDirRecLength(length);
dirEntryPtr->nameLength = length;
strcpy(dirEntryPtr->fileName, fileName);
offset = dirEntryPtr->recordLength;
dirEntryPtr = (FsDirEntry *)((int)block + offset);
fileName = "..";
length = strlen(fileName);
dirEntryPtr->fileNumber = FS_ROOT_FILE_NUMBER;
dirEntryPtr->recordLength = FS_DIR_BLOCK_SIZE - offset;
dirEntryPtr->nameLength = length;
strcpy(dirEntryPtr->fileName, fileName);
/*
* Fill out the rest of the directory with empty blocks.
*/
for (dirEntryPtr = (FsDirEntry *)&block[FS_DIR_BLOCK_SIZE], i = 1;
i < FS_NUM_LOST_FOUND_BLOCKS * FS_BLOCK_SIZE / FS_DIR_BLOCK_SIZE;
i++,dirEntryPtr=(FsDirEntry *)((int)dirEntryPtr + FS_DIR_BLOCK_SIZE)) {
dirEntryPtr->fileNumber = 0;
dirEntryPtr->recordLength = FS_DIR_BLOCK_SIZE;
dirEntryPtr->nameLength = 0;
}
if (printOnly) {
printf("Lost+found Directory\n");
offset = 0;
dirEntryPtr = (FsDirEntry *)block;
Disk_PrintDirEntry(dirEntryPtr);
offset += dirEntryPtr->recordLength;
dirEntryPtr = (FsDirEntry *)((int)block + offset);
Disk_PrintDirEntry(dirEntryPtr);
status = 0;
} else {
status = Disk_BlockWrite(firstPartFID, headerPtr,
headerPtr->dataOffset + 1,
FS_NUM_LOST_FOUND_BLOCKS, block);
}
return(status);
}
d1089 1
d1109 1
a1109 4
ScanDiskTab(firstPartFID, partition, diskType)
int firstPartFID;
char partition;
char *diskType;
d1236 1
a1236 1
* Set up a disk header and write it to sector 16.
d1245 1
d1257 1
a1257 1
header.partition = partition - 'a';
d1271 14
d1287 1
a1287 1
status = Disk_SectorWrite(firstPartFID, 16, 1, (Address)headerPtr);
d1311 881
@